init(); srand(time(NULL)); int val[5]; for(i=0; i<5; i++) { val[i] = rand(); } memcpy(g_my_id,(char*)val,20); DEBUG(for (int i=0;i<20;i++) printf("%02X ",(unsigned char)g_my_id[i]);puts("");) strncpy(g_my_ip,argv[2],strlen(argv[2])); g_my_ip[strlen(argv[2])+1] = '\0'; g_filename = argv[3]; g_torrentmeta = parsetorrentfile(argv[1]); memcpy(g_infohash,g_torrentmeta->info_hash,20); g_filelen = g_torrentmeta->length; g_num_pieces = g_torrentmeta->num_pieces; for (i = 0; i <g_torrentmeta->filenum; i++){ g_torrentmeta->flist[i].fp = createfile(g_torrentmeta->flist[i].filename, g_torrentmeta->flist[i].size); } g_bitfield = gen_bitfield(g_torrentmeta->pieces,g_torrentmeta->piece_len, g_torrentmeta->num_pieces); g_filedata = (char*)malloc(g_filelen*sizeof(char)); piece_counter = (int *)malloc(sizeof(int)*g_torrentmeta->num_pieces); memset(piece_counter,0,sizeof(int)*g_torrentmeta->num_pieces); announce_url_t* announce_info; announce_info = parse_announce_url(g_torrentmeta->announce); // 提取tracker url中的IP地址
int main ( int argc, char *argv[] ) { int i; //init ListHead list_init(&P2PCB_head); list_init(&downloading_piece_head); //init mutex pthread_mutexattr_t mutex_attr; pthread_mutexattr_settype(&mutex_attr,PTHREAD_MUTEX_RECURSIVE_NP); pthread_mutex_init(&P2P_mutex,&mutex_attr); pthread_mutex_init(&download_mutex,&mutex_attr); pthread_mutex_init(&firstReq_mutex,&mutex_attr); pthread_mutex_init(&pieceCounter_mutex,&mutex_attr); // <-- deal with argument --> globalArgs.port = 6881; globalArgs.isseed = 0; globalArgs.torrentpath = NULL; int opt; while(opt = getopt(argc, argv, optstring), opt != -1){ switch(opt){ case 'p': { globalArgs.port = atoi(optarg); break; } case 'i': { globalArgs.isseed = atoi(optarg); break; } case 'v': { globalArgs.verbose = true; break; } case 'h': { useage(); exit(0); break; } case '?': { useage(); exit(0); break; } default: { assert(false && "some amazing thing happen when parser argument"); break; } } } globalArgs.torrentpath = argv[argc - 1]; // <-- end --> #ifdef DEBUG printf("isseed:%d\n", globalArgs.isseed); printf("port:%d\n", globalArgs.port); printf("torrentpath:%s\n", globalArgs.torrentpath); printf("verbose:%s\n", (globalArgs.verbose)?"true":"false"); #endif // <-- set value of globalInfo --> init_peer_id(globalInfo.g_my_id); globalInfo.g_peer_port = globalArgs.port; globalInfo.g_torrentmeta = parsetorrentfile(globalArgs.torrentpath); if (globalInfo.g_torrentmeta == NULL){ printf("Error when parsing torrent file\n"); return -1; } for (i = 0; i < globalInfo.g_torrentmeta->filenum; i++){ globalInfo.g_torrentmeta->flist[i].fp = createfile(globalInfo.g_torrentmeta->flist[i].filename, globalInfo.g_torrentmeta->flist[i].size); } globalInfo.bitfield = gen_bitfield(globalInfo.g_torrentmeta->pieces, globalInfo.g_torrentmeta->piece_len, globalInfo.g_torrentmeta->num_pieces); #ifdef DEBUG printf("bitfield:"); for (i = 0; i <= globalInfo.g_torrentmeta->num_pieces / 8; i++) printf("%X ", globalInfo.bitfield[i]); printf("\n"); #endif //set piece_counter for "least first" piece_counter = (int *)malloc(sizeof(int)*globalInfo.g_torrentmeta->num_pieces); memset(piece_counter,0,sizeof(int)*globalInfo.g_torrentmeta->num_pieces); // <-- end --> // <-- create socket listen to port --> listenfd = make_listen_port(globalInfo.g_peer_port); if (listenfd == 0){ printf("Error when create socket for binding:%s\n", strerror(errno)); exit(-1); } pthread_t p_daemon; if (pthread_create(&p_daemon, NULL, daemon_listen, (void *)listenfd) != 0){ int tmp = errno; printf("Error when create daemon thread: %s\n", strerror(tmp)); return -1; } pthread_t p_speed; if (pthread_create(&p_speed, NULL, show_speed, NULL) != 0){ int tmp = errno; printf("Error when create show_speed thread: %s\n", strerror(tmp)); return -1; } announce_url_t *announce_info = parse_announce_url(globalInfo.g_torrentmeta->announce); if (globalArgs.verbose == true){ printf("host: %s:%d\n", announce_info->hostname, announce_info->port); } struct hostent *tracker_hostent = gethostbyname(announce_info->hostname); if (tracker_hostent == NULL){ printf("Error when get tracker host\n"); return -1; } strcpy(globalInfo.g_tracker_ip, inet_ntoa(*((struct in_addr *)tracker_hostent->h_addr_list[0]))); globalInfo.g_tracker_port = announce_info->port; free(announce_info); announce_info = NULL; // set the action after recv ctrl-c signal(SIGINT, client_shutdown); signal(SIGPIPE, SIG_IGN); int event_value = BT_STARTED; while(true){ int sockfd = connect_to_host(globalInfo.g_tracker_ip, globalInfo.g_tracker_port); #ifdef DEBUG printf("Sending request to tracker\n"); #endif int request_len = 0; char *request = make_tracker_request(&globalInfo, event_value, &request_len); event_value = -1; #ifdef DEBUG printf("%s", request); #endif if (send(sockfd, request, request_len, 0) == -1){ int tmp = errno; printf("%s\n", strerror(tmp)); // error when connect to tracker, wait some time and try again sleep(5); close(sockfd); free(request); continue; } tracker_response *tr = preprocess_tracker_response(sockfd); close(sockfd); globalInfo.g_tracker_response = get_tracker_data(tr->data, tr->size); free(tr->data); free(tr); #ifdef DEBUG printf("Num Peers: %d\n", globalInfo.g_tracker_response->numpeers); for (i = 0; i < globalInfo.g_tracker_response->numpeers; i++){ printf("Peer ip: %s:%d\n", globalInfo.g_tracker_response->peers[i].ip, globalInfo.g_tracker_response->peers[i].port); } #endif for (i = 0; i < globalInfo.g_tracker_response->numpeers; i++){ if (!exist_ip(globalInfo.g_tracker_response->peers[i].ip)){ pthread_t tid; p2p_thread_param *param = (p2p_thread_param *)malloc(sizeof(p2p_thread_param)); param->is_connecter = 1; param->port = globalInfo.g_tracker_response->peers[i].port; strcpy(param->ip, globalInfo.g_tracker_response->peers[i].ip); if (pthread_create(&tid, NULL, process_p2p_conn, param) != 0){ printf("Error when create thread to connect peer\n"); } else { printf("Success create thread to connect peer %s\n", globalInfo.g_tracker_response->peers[i].ip); } } } printf("sleep %d seconds\n", globalInfo.g_tracker_response->interval); sleep(globalInfo.g_tracker_response->interval); } return EXIT_SUCCESS; } /* ---------- end of function main ---------- */