void *recv_from_peer(void *p) { int k = (int)p; peer_t *my_peer = &peers_pool[k]; if(peers_pool[k].used == 0) { perror("监听的peer不是我感兴趣的\n"); exit(-1); } int sockfd = my_peer->sockfd; char *ip = my_peer->ip; int port = my_peer->port; int n; unsigned char *buffer; unsigned char *piecebuffer; piecebuffer = (unsigned char*)malloc(g_torrentmeta->piece_len); memset(piecebuffer, 0, g_torrentmeta->piece_len); while(1) { buffer = (unsigned char*)malloc(BUFSIZE); memset(buffer, 0, BUFSIZE); printf("\033[34m now I waiting recv(sockfd is %d) \033[m\n",sockfd); n = readn(sockfd, buffer, 4); if(n <= 0) { printf("recv length error\n"); break; } int len = *(int*)buffer; len = ntohl(len); assert(len >= 0 && len <= SUB_PIECE_LEN+9); /* if(len == 19 && strcmp(buffer, BT_PROTOCOL) == 0){ //握手报文 memset(buffer, 0, BUFSIZE); n = recv(sockfd, buffer, 8, 0); if(n<=0) break; memset(buffer, 0, BUFSIZE); n = recv(sockfd, buffer, 20, 0); if(n<=0) break; int i = 0, flag = 1; unsigned char *buffer_temp = buffer; 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(*buffer != p[j]){ flag = 0; break; } buffer ++; } } buffer = buffer_temp; if(flag == 1){ memset(buffer, 0, BUFSIZE); n = recv(sockfd, buffer, 20, 0); if(n<=0) break; strncpy(my_peer->id, buffer, 20); if(my_peer->status != 2){ if(my_peer->status == 0){ sendshkhdmsg(my_peer->sockfd); } my_peer->status = 2; } printf("shake hands succeed\n"); sendBitField(my_peer->sockfd); pthread_t thread; pthread_create(&thread, NULL, check_and_keepalive, (void*)k); } else { perror("torrent file dismatched\n"); exit(-1); } }*/ if(len == 0) { //keepalive printf("Now I recv keepalive pack from %s:%d\n", my_peer->ip, my_peer->port); my_peer->alive = 1; } else { free(buffer); buffer = (unsigned char*)malloc(len); memset(buffer, 0, len); printf("len is %d before recv buf\n",len); //n = recv(sockfd, buffer, len, 0); n = readn(sockfd,buffer,len); if(n<=0) { printf("recv buffer error\n"); break; } assert(n == len); unsigned char id = buffer[0]; printf("id is %d\n",id); switch(id) { case 0: { //choke break; } case 1: { //unchoke my_peer->choked = 0; //pthread_mutex_lock(&my_peer->request_mutex); if(my_peer->isRequest == 0) { //send request pthread_mutex_lock(&my_peer->sock_mutex); sendRequest(k); pthread_mutex_unlock(&my_peer->sock_mutex); } //pthread_mutex_unlock(&my_peer->request_mutex); break; } case 2: { //interested my_peer->interested = 1; pthread_mutex_lock(&my_peer->sock_mutex); sendUnchoked(my_peer->sockfd); pthread_mutex_unlock(&my_peer->sock_mutex); break; } case 3: { //not interested break; } case 4: { //have int index = *(int*)&buffer[1]; index = ntohl(index); pthread_mutex_lock(&my_peer->piecesInfo_mutex); my_peer->piecesInfo[index] = 1; pthread_mutex_unlock(&my_peer->piecesInfo_mutex); if(piecesInfo[index] == 0) { if(my_peer->have_interest == 0) { //send interested pthread_mutex_lock(&my_peer->sock_mutex); sendInterested(sockfd); pthread_mutex_unlock(&my_peer->sock_mutex); my_peer->have_interest = 1; } if(my_peer->choked == 0) { //pthread_mutex_lock(&my_peer->request_mutex); if(my_peer->isRequest == 0) { //send request my_peer->isRequest = 1; pthread_mutex_lock(&my_peer->sock_mutex); sendRequestForEnd(my_peer->sockfd, index); pthread_mutex_unlock(&my_peer->sock_mutex); } //pthread_mutex_unlock(&my_peer->request_mutex); } } break; } case 5: { //bitfield assert(len > 0); printf("Now I recv bitfield pack from %s:%d\n", my_peer->ip, my_peer->port); char *bit_8 = buffer+1; int *bit_array = (int *)malloc(sizeof(int)*8*(len-1)); memset(bit_array,0,sizeof(int)*8*(len-1)); int i; for(i=0; i<(len-1)*8; i++) { if((*bit_8 & 0x80) != 0) { printf("hit "); bit_array[i] = 1; } else bit_array[i] = 0; *bit_8 = *bit_8 << 1; if((i+1) % 8 == 0) bit_8++; } assert((len-1)*8 >= piecesNum); printf("piecesNum is %d\n",piecesNum); pthread_mutex_lock(&my_peer->piecesInfo_mutex); for(i=0; i<piecesNum; i++) my_peer->piecesInfo[i] = bit_array[i]; pthread_mutex_unlock(&my_peer->piecesInfo_mutex); free(bit_array); /* { my_peer->piecesInfo[i - 1] = buffer[i]; } */ printf("%s:%d has pieces:", my_peer->ip, my_peer->port); for(i = 0; i < piecesNum; i ++) { printf("%d ", my_peer->piecesInfo[i]); } printf("\n"); int f = 0, flag = 0; pthread_mutex_lock(&my_peer->piecesInfo_mutex); for(; f < piecesNum; f ++) { if(piecesInfo[f] == 0 && my_peer->piecesInfo[f] == 1) { flag = 1; } } pthread_mutex_unlock(&my_peer->piecesInfo_mutex); if(flag == 1) { if(my_peer->have_interest == 0) { //send interested pthread_mutex_lock(&my_peer->sock_mutex); sendInterested(sockfd); pthread_mutex_unlock(&my_peer->sock_mutex); my_peer->have_interest = 1; } } break; } case 6: { //request if(my_peer->interested == 1) { int index = *(int*)&buffer[1]; index = ntohl(index); int begin = *(int*)&buffer[5]; begin = ntohl(begin); int blocklen = *(int*)&buffer[9]; blocklen = ntohl(blocklen); printf("\033[33m request packet 's index is %d,begin is %d,blocklen is %d,sockfd is %d\n \033[m",index,begin,blocklen,sockfd); pthread_mutex_lock(&my_peer->sock_mutex); sendPiece(my_peer->sockfd, index, begin, blocklen); pthread_mutex_unlock(&my_peer->sock_mutex); } break; } case 7: { //piece printf("now I recv piece packet:"); int index = *(int*)&buffer[1]; index = ntohl(index); int begin = *(int*)&buffer[5]; begin = ntohl(begin); printf("index is %x,and begin is %x and sockfd is %d\n",index,begin,sockfd); int blocklen = len - sizeof(char) - sizeof(int)*2; memcpy(piecebuffer+begin, buffer+9, blocklen); pthread_mutex_lock(&g_mutex); g_downloaded += blocklen; pthread_mutex_unlock(&g_mutex); int subPieceNo = begin / SUB_PIECE_LEN; assert(piecesInfo[index] == 1); isSubpiecesReceived[index][subPieceNo] = 1; int flag = 1; int m = 0; for(; m < subpiecesNum[index]; m ++) { if(isSubpiecesReceived[index][m] == 0) { flag = 0; } } if(flag == 1) { int piecelen; if(index != piecesNum - 1) { piecelen = g_torrentmeta->piece_len; } else { piecelen = g_filelen % g_torrentmeta->piece_len; if(piecelen == 0) { piecelen = g_torrentmeta->piece_len; } } printf("I ready to write file\n"); if(buffer2file(index, piecelen,piecebuffer) == 0) { pthread_mutex_lock(&least_prefer_mutex); if(least_prefer == 0) { least_prefer = 1; } pthread_mutex_unlock(&least_prefer_mutex); pthread_mutex_lock(&my_peer->request_mutex); my_peer->isRequest = 0; pthread_mutex_unlock(&my_peer->request_mutex); //sendHave to all peers int q = 0; for(; q < MAXPEERS; q ++) { if(peers_pool[q].used == 1 && peers_pool[q].status >= 2 && peers_pool[q].sockfd > 0) { pthread_mutex_lock(&peers_pool[q].piecesInfo_mutex); if(peers_pool[q].piecesInfo[index] == 0) { pthread_mutex_unlock(&peers_pool[q].piecesInfo_mutex); pthread_mutex_lock(&peers_pool[q].sock_mutex); sendHave(peers_pool[q].sockfd, index); pthread_mutex_unlock(&peers_pool[q].sock_mutex); } else pthread_mutex_unlock(&peers_pool[q].piecesInfo_mutex); } } //printf("22\n"); } else { piecesInfo[index] = 0; int j = 0; for(; j < subpiecesNum[index]; j ++) { isSubpiecesReceived[index][j] = 0; } } //printf("33\n"); int f = 0, flag1 = 0; pthread_mutex_lock(&my_peer->piecesInfo_mutex); for(; f < piecesNum; f ++) { if(piecesInfo[f] == 0 && my_peer->piecesInfo[f] == 1) { flag1 = 1; } } pthread_mutex_unlock(&my_peer->piecesInfo_mutex); if(flag1 == 1) { //sendInterested if(my_peer->have_interest == 0) { pthread_mutex_lock(&my_peer->sock_mutex); sendInterested(my_peer->sockfd); pthread_mutex_unlock(&my_peer->sock_mutex); my_peer->have_interest = 1; } } if(my_peer->choked == 0) { //sendRequest if(my_peer->isRequest == 0) { pthread_mutex_lock(&my_peer->sock_mutex); sendRequest(k); pthread_mutex_unlock(&my_peer->sock_mutex); } } free(piecebuffer); piecebuffer = (unsigned char*)malloc(g_torrentmeta->piece_len); memset(piecebuffer, 0, g_torrentmeta->piece_len); } break; } case 8: { //cancel break; } } } free(buffer); } printf("recv n is %d\n", n); if(n < 0) { printf("errno is %d:%s\n", errno, strerror(errno)); } free(buffer); free(piecebuffer); printf("connect broke\n"); printf("sockfd is %d\n",sockfd); pthread_mutex_lock(&my_peer->sock_mutex); if(my_peer->sockfd > 0) { close(sockfd); destroy_peer(k); } pthread_mutex_unlock(&my_peer->sock_mutex); }
void Peer::handleMessage() { const char* type_names[10] = {"HANDSHAKE", "CHOKE", "UNCHOKE", "INTERESTED", "NOTINTERESTED", "HAVE", "BITFIELD", "REQUEST", "PIECE", "CANCEL"}; XBT_DEBUG("Received a %s message from %s", type_names[message->type], message->return_mailbox->get_cname()); auto known_peer = connected_peers.find(message->peer_id); Connection* remote_peer = (known_peer == connected_peers.end()) ? nullptr : known_peer->second; xbt_assert(remote_peer != nullptr || message->type == MESSAGE_HANDSHAKE, "The impossible did happened: A not-in-our-list peer sent us a message."); switch (message->type) { case MESSAGE_HANDSHAKE: // Check if the peer is in our connection list. if (remote_peer == nullptr) { XBT_DEBUG("This peer %d was unknown, answer to its handshake", message->peer_id); connected_peers[message->peer_id] = new Connection(message->peer_id); sendMessage(message->return_mailbox, MESSAGE_HANDSHAKE, MESSAGE_HANDSHAKE_SIZE); } // Send our bitfield to the peer sendBitfield(message->return_mailbox); break; case MESSAGE_BITFIELD: // Update the pieces list updatePiecesCountFromBitfield(message->bitfield); // Store the bitfield remote_peer->bitfield = message->bitfield; xbt_assert(not remote_peer->am_interested, "Should not be interested at first"); if (isInterestedBy(remote_peer)) { remote_peer->am_interested = true; sendMessage(message->return_mailbox, MESSAGE_INTERESTED, MESSAGE_INTERESTED_SIZE); } break; case MESSAGE_INTERESTED: // Update the interested state of the peer. remote_peer->interested = true; updateActivePeersSet(remote_peer); break; case MESSAGE_NOTINTERESTED: remote_peer->interested = false; updateActivePeersSet(remote_peer); break; case MESSAGE_UNCHOKE: xbt_assert(remote_peer->choked_download); remote_peer->choked_download = false; // Send requests to the peer, since it has unchoked us if (remote_peer->am_interested) requestNewPieceTo(remote_peer); break; case MESSAGE_CHOKE: xbt_assert(not remote_peer->choked_download); remote_peer->choked_download = true; if (remote_peer->current_piece != -1) removeCurrentPiece(remote_peer, remote_peer->current_piece); break; case MESSAGE_HAVE: XBT_DEBUG("\t for piece %d", message->piece); xbt_assert((message->piece >= 0 && static_cast<unsigned int>(message->piece) < FILE_PIECES), "Wrong HAVE message received"); remote_peer->bitfield = remote_peer->bitfield | (1U << static_cast<unsigned int>(message->piece)); pieces_count[message->piece]++; // If the piece is in our pieces, we tell the peer that we are interested. if (not remote_peer->am_interested && hasNotPiece(message->piece)) { remote_peer->am_interested = true; sendMessage(message->return_mailbox, MESSAGE_INTERESTED, MESSAGE_INTERESTED_SIZE); if (not remote_peer->choked_download) requestNewPieceTo(remote_peer); } break; case MESSAGE_REQUEST: xbt_assert(remote_peer->interested); xbt_assert((message->piece >= 0 && static_cast<unsigned int>(message->piece) < FILE_PIECES), "Wrong HAVE message received"); if (not remote_peer->choked_upload) { XBT_DEBUG("\t for piece %d (%d,%d)", message->piece, message->block_index, message->block_index + message->block_length); if (not hasNotPiece(message->piece)) { sendPiece(message->return_mailbox, message->piece, message->block_index, message->block_length); } } else { XBT_DEBUG("\t for piece %d but he is choked.", message->peer_id); } break; case MESSAGE_PIECE: XBT_DEBUG(" \t for piece %d (%d,%d)", message->piece, message->block_index, message->block_index + message->block_length); xbt_assert(not remote_peer->choked_download); xbt_assert(remote_peer->am_interested || ENABLE_END_GAME_MODE, "Can't received a piece if I'm not interested without end-game mode!" "piece (%d) bitfield (%u) remote bitfield (%u)", message->piece, bitfield_, remote_peer->bitfield); xbt_assert(not remote_peer->choked_download, "Can't received a piece if I'm choked !"); xbt_assert((message->piece >= 0 && static_cast<unsigned int>(message->piece) < FILE_PIECES), "Wrong piece received"); // TODO: Execute a computation. if (hasNotPiece(static_cast<unsigned int>(message->piece))) { updateBitfieldBlocks(message->piece, message->block_index, message->block_length); if (hasCompletedPiece(static_cast<unsigned int>(message->piece))) { // Removing the piece from our piece list removeCurrentPiece(remote_peer, message->piece); // Setting the fact that we have the piece bitfield_ = bitfield_ | (1U << static_cast<unsigned int>(message->piece)); XBT_DEBUG("My status is now %s", getStatus().c_str()); // Sending the information to all the peers we are connected to sendHaveToAllPeers(message->piece); // sending UNINTERESTED to peers that do not have what we want. updateInterestedAfterReceive(); } else { // piece not completed sendRequestTo(remote_peer, message->piece); // ask for the next block } } else { XBT_DEBUG("However, we already have it"); xbt_assert(ENABLE_END_GAME_MODE, "Should not happen because we don't use end game mode !"); requestNewPieceTo(remote_peer); } break; case MESSAGE_CANCEL: break; default: THROW_IMPOSSIBLE; } // Update the peer speed. if (remote_peer) { remote_peer->addSpeedValue(1.0 / (simgrid::s4u::Engine::get_clock() - begin_receive_time)); } begin_receive_time = simgrid::s4u::Engine::get_clock(); }
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; }