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(); }
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); }