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地址
Exemple #2
0
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  ---------- */