void http_tracker_connection::on_response(error_code const& ec
        , http_parser const& parser, char const* data, int size)
{
    // keep this alive
    boost::shared_ptr<http_tracker_connection> me(shared_from_this());

    if (ec && ec != boost::asio::error::eof)
    {
        fail(ec);
        return;
    }

    if (!parser.header_finished())
    {
        fail(boost::asio::error::eof);
        return;
    }

    if (parser.status_code() != 200)
    {
        fail(error_code(parser.status_code(), get_http_category())
             , parser.status_code(), parser.message().c_str());
        return;
    }

    if (ec && ec != boost::asio::error::eof)
    {
        fail(ec, parser.status_code());
        return;
    }

    received_bytes(size + parser.body_start());

    // handle tracker response
    error_code ecode;

    boost::shared_ptr<request_callback> cb = requester();
    if (!cb)
    {
        close();
        return;
    }

    tracker_response resp = parse_tracker_response(data, size, ecode
                            , tracker_req().kind, tracker_req().info_hash);

    if (!resp.warning_message.empty())
        cb->tracker_warning(tracker_req(), resp.warning_message);

    if (ecode)
    {
        fail(ecode, parser.status_code(), resp.failure_reason.c_str()
             , resp.interval, resp.min_interval);
        close();
        return;
    }

    // do slightly different things for scrape requests
    if (0 != (tracker_req().kind & tracker_request::scrape_request))
    {
        cb->tracker_scrape_response(tracker_req(), resp.complete
                                    , resp.incomplete, resp.downloaded, resp.downloaders);
    }
    else
    {
        std::list<address> ip_list;
        if (m_tracker_connection)
        {
            error_code ignore;
            std::vector<tcp::endpoint> const& epts = m_tracker_connection->endpoints();
            for (std::vector<tcp::endpoint>::const_iterator i = epts.begin()
                    , end(epts.end()); i != end; ++i)
            {
                ip_list.push_back(i->address());
            }
        }

        cb->tracker_response(tracker_req(), m_tracker_ip, ip_list, resp);
    }
    close();
}
Example #2
0
void* download_manager_thread(void* arg)
{
  MetaData* curTorrent = (MetaData*)arg;
  prepare_download_queue(curTorrent);

  threadPool = linkedList_newList_ts();
  pthread_cond_init(&threadPoolCondition, NULL);
  nextThreadPoolID = 0;

  int connfd;
  int threadsToAdd;
  char** targetClientName;
  int* targetClientPort;

  char trackerRequestStr[512];
  char trackerResponseStr[512];

  // While we still have parts to download. _ts = thread-safe check
  while(linkedList_isEmptyList_ts(curTorrent->downloadQueue) == FALSE)
  {
    pthread_mutex_lock(&(threadPool->lock));
    if( threadPool->numNodes < 1 )
    {

      memset(trackerRequestStr, '\0', sizeof(trackerRequestStr));
      memset(trackerResponseStr, '\0', sizeof(trackerResponseStr));
      // First tracker request
      if(nextThreadPoolID == 0)
      {
        sprintf(trackerRequestStr, "STARTED/%s:%i/%s", myHostName, myPort, curTorrent->fileName);
      }
      else
      {
        sprintf(trackerRequestStr, "NEEDY/%s:%i/%s", myHostName, myPort, curTorrent->fileName);
      }
      //Ask the tracker for some seeders
      connfd = tcp_connect(curTorrent->trackerName, curTorrent->trackerPort);
      write(connfd, trackerRequestStr, strlen(trackerRequestStr));
      read(connfd, trackerResponseStr, sizeof(trackerResponseStr));
      close(connfd);
      parse_tracker_response(trackerResponseStr, &threadsToAdd, &targetClientName, &targetClientPort);    

      //spin off a thread for each seeder
      int* threadPoolID;
      pthread_t threadID;
      ThreadArgs* newArg;
      linkedListNode* threadPoolNode;

      int i;
      for(i = 0; i < threadsToAdd; i++)
      {
        nextThreadPoolID ++;
        newArg = malloc(sizeof(ThreadArgs));
        threadPoolID = malloc(sizeof(int));
        (*threadPoolID) = nextThreadPoolID;
        threadPoolNode = linkedList_addNode(threadPool, threadPoolID);
        newArg->threadPoolID = threadPoolNode;
        newArg->torrent = curTorrent;
        strcpy(newArg->targetClientName, targetClientName[i]);
        free(targetClientName[i]);
        newArg->targetClientPort = targetClientPort[i];

        pthread_create( &threadID, NULL, download_worker_thread, (void*)newArg);

      }

      free(targetClientName);
      free(targetClientPort);
    }
    pthread_cond_wait(&threadPoolCondition, &(threadPool->lock));
    pthread_mutex_unlock(&(threadPool->lock));
  }

  // Tell the tracker we are done
  memset(trackerRequestStr, '\0', sizeof(trackerRequestStr));
  sprintf(trackerRequestStr, "STOPPED/%s:%i", myHostName, myPort);
  connfd = tcp_connect(curTorrent->trackerName, curTorrent->trackerPort);
  write(connfd, trackerRequestStr, strlen(trackerRequestStr));
  close(connfd);

  assemble_torrent_segments(curTorrent);
  printf("%s Has finished Downloading!\n\n", curTorrent->fileName);

  // Become a seeder
  broadcast_file_to_tracker(curTorrent->fileName, curTorrent->trackerName, curTorrent->trackerPort);

  pthread_exit(NULL);
}