Example #1
0
	directory::directory(std::string const& path, error_code& ec)
		: m_done(false)
	{
		ec.clear();
#ifdef TORRENT_WINDOWS
		// the path passed to FindFirstFile() must be
		// a pattern
		std::string f = convert_separators(path);
		if (!f.empty() && f[f.size()-1] != '\\') f += "\\*";
		else f += "*";
#if TORRENT_USE_WSTRING
#define FindFirstFile_ FindFirstFileW
		std::wstring p = convert_to_wstring(f);
#else
#define FindFirstFile_ FindFirstFileA
		std::string p = convert_to_native(f);
#endif
		m_handle = FindFirstFile_(p.c_str(), &m_fd);
		if (m_handle == INVALID_HANDLE_VALUE)
		{
			ec.assign(GetLastError(), boost::system::get_system_category());
			m_done = true;
			return;
		}
#else

		memset(&m_dirent, 0, sizeof(dirent));
		m_name[0] = 0;

		// the path passed to opendir() may not
		// end with a /
		std::string p = path;
		if (!path.empty() && path[path.size()-1] == '/')
			p.resize(path.size()-1);

		p = convert_to_native(p);
		m_handle = opendir(p.c_str());
		if (m_handle == 0)
		{
			ec.assign(errno, boost::system::get_generic_category());
			m_done = true;
			return;
		}
		// read the first entry
		next(ec);
#endif
	}
Example #2
0
		std::string get_symlink_path(std::string const& p)
		{
#if defined TORRENT_WINDOWS
			return "";
#else
			std::string path = convert_to_native(p);
			return get_symlink_path_impl(p.c_str());
#endif
		}
Example #3
0
	void rename(std::string const& inf, std::string const& newf, error_code& ec)
	{
		ec.clear();

#if TORRENT_USE_WSTRING && defined TORRENT_WINDOWS
		std::wstring f1 = convert_to_wstring(inf);
		std::wstring f2 = convert_to_wstring(newf);
		if (_wrename(f1.c_str(), f2.c_str()) < 0)
#else
		std::string f1 = convert_to_native(inf);
		std::string f2 = convert_to_native(newf);
		if (::rename(f1.c_str(), f2.c_str()) < 0)
#endif
		{
			ec.assign(errno, boost::system::get_generic_category());
			return;
		}
	}
Example #4
0
 void add_transfer_params::dump() const
     {
         DBG("add_transfer_params::dump");
         DBG("file hash: " << file_hash << " all hashes size: " << piece_hashses.size());
         DBG("file path: " << convert_to_native(file_path));
         DBG("file size: " << file_size);
         DBG("accepted: " << accepted <<
             " requested: " << requested <<
             " transf: " << transferred <<
             " priority: " << priority);
     }
Example #5
0
	void remove(std::string const& inf, error_code& ec)
	{
		ec.clear();

#ifdef TORRENT_WINDOWS
		// windows does not allow trailing / or \ in
		// the path when removing files
		std::string pruned;
		if (inf[inf.size() - 1] == '/'
			|| inf[inf.size() - 1] == '\\')
			pruned = inf.substr(0, inf.size() - 1);
		else
			pruned = inf;
#if TORRENT_USE_WSTRING
#define DeleteFile_ DeleteFileW
#define RemoveDirectory_ RemoveDirectoryW
		std::wstring f = convert_to_wstring(pruned);
#else
#define DeleteFile_ DeleteFileA
#define RemoveDirectory_ RemoveDirectoryA
		std::string f = convert_to_native(pruned);
#endif
		if (DeleteFile_(f.c_str()) == 0)
		{
			if (GetLastError() == ERROR_ACCESS_DENIED)
			{
				if (RemoveDirectory_(f.c_str()) != 0)
					return;
			}
			ec.assign(GetLastError(), boost::system::get_system_category());
			return;
		}
#else // TORRENT_WINDOWS
		std::string f = convert_to_native(inf);
		if (::remove(f.c_str()) < 0)
		{
			ec.assign(errno, boost::system::get_generic_category());
			return;
		}
#endif // TORRENT_WINDOWS
	}
Example #6
0
	void stat_file(std::string inf, file_status* s
		, error_code& ec, int flags)
	{
		ec.clear();
#ifdef TORRENT_WINDOWS
		// apparently windows doesn't expect paths
		// to directories to ever end with a \ or /
		if (!inf.empty() && (inf[inf.size() - 1] == '\\'
			|| inf[inf.size() - 1] == '/'))
			inf.resize(inf.size() - 1);
#endif

#if TORRENT_USE_WSTRING && defined TORRENT_WINDOWS
		std::wstring f = convert_to_wstring(inf);
#else
		std::string f = convert_to_native(inf);
#endif

#ifdef TORRENT_WINDOWS
		struct _stati64 ret;
#if TORRENT_USE_WSTRING
		if (_wstati64(f.c_str(), &ret) < 0)
#else
		if (_stati64(f.c_str(), &ret) < 0)
#endif
		{
			ec.assign(errno, boost::system::get_generic_category());
			return;
		}
#else
		struct stat ret;
		int retval;
		if (flags & dont_follow_links)
			retval = ::lstat(f.c_str(), &ret);
		else
			retval = ::stat(f.c_str(), &ret);
		if (retval < 0)
		{
			ec.assign(errno, boost::system::get_generic_category());
			return;
		}
#endif // TORRENT_WINDOWS

		s->file_size = ret.st_size;
		s->atime = ret.st_atime;
		s->mtime = ret.st_mtime;
		s->ctime = ret.st_ctime;
		s->mode = ret.st_mode;
	}
Example #7
0
	void create_directory(std::string const& f, error_code& ec)
	{
		ec.clear();

#if defined TORRENT_WINDOWS && TORRENT_USE_WSTRING
#define CreateDirectory_ CreateDirectoryW
		std::wstring n = convert_to_wstring(f);
#else
#define CreateDirectory_ CreateDirectoryA
		std::string n = convert_to_native(f);
#endif

#ifdef TORRENT_WINDOWS
		if (CreateDirectory_(n.c_str(), 0) == 0
			&& GetLastError() != ERROR_ALREADY_EXISTS)
			ec.assign(GetLastError(), boost::system::get_system_category());
#else
		int ret = mkdir(n.c_str(), 0777);
		if (ret < 0 && errno != EEXIST)
			ec.assign(errno, boost::system::get_generic_category());
#endif
	}
	bool read_data(char* data, size_type offset, size_type size, size_type& read_size)
	{
		if (m_abort) return false;

		boost::mutex::scoped_lock lock(m_notify_mutex);
		const torrent_info& info = m_handle.get_torrent_info();
		bool ret = false;

		read_size = 0;

#if defined(_DEBUG) && defined(WIN32)
		unsigned int time = GetTickCount();
#endif
		// 计算偏移所在的片.
		int index = offset / info.piece_length();
		BOOST_ASSERT(index >= 0 && index < info.num_pieces());
		if (index >= info.num_pieces() || index < 0)
			return ret;
		torrent_status status = m_handle.status(torrent_handle::query_pieces);
		bitfield &pieces = status.pieces;
		if (!pieces.empty())
		{
			if (status.state != torrent_status::finished &&
				 status.state != torrent_status::seeding &&
				 status.state != torrent_status::downloading)
				return ret;

			// 查看是否需要计算新的下载位置.
			bool set_download_point = true;
			int min_piece_position = std::min(index, m_cache_offset);
			int max_piece_position = std::max(index, m_cache_offset);
			if (min_piece_position != -1)// min_piece_position 为-1, 需要设置下载位置, 也就是首次下载位置.
			{
				// 不为-1, 先计算下载点位置, 如果相等, 说明上一次已经设置过下载点位置.
				if (min_piece_position == max_piece_position)
					set_download_point = false;
				else
				{
					// 查看上次请求的位置和当前位置是否连接已经下载的分块区域, 如果下载区域已经连接成块.
					// 那么也不需要再设置下载点位置.
					for (; min_piece_position < max_piece_position; min_piece_position++)
						if (!pieces.get_bit(min_piece_position))
							break;
					// 表示下载块连接成区域.
					if (min_piece_position == max_piece_position)
						set_download_point = false;
				}
			}

			// 缓存下载位置.
			m_cache_offset = index;

			// 计算下载位置, 如果有需要, 则修改下载位置.
			if (set_download_point)
			{
				std::vector<int> new_point(pieces.size(), 1);
				new_point[index] = 7;
				m_handle.prioritize_pieces(new_point);
			}

			// 如果有数据, 则进入读取.
			if (pieces.get_bit(index))
			{
				// 保存参数信息.
				m_current_buffer = data;
				m_read_offset = offset;
				m_read_size = &read_size;
				m_request_size = size;

				// 提交请求.
				m_handle.read_piece(index, boost::bind(&extern_read_op::on_read, this, _1, _2, _3));

				// 等待请求返回.
				m_notify.wait(lock);

				// 读取字节数.
				if (read_size != 0)
					ret = true;
			}
		}
		else
		{
			// 直接读取文件.
			if (m_file_path.string() == "" || !m_file.is_open())
			{
				boost::filesystem::path path = m_handle.save_path();
				const file_storage& stor = info.files();
				std::string name = stor.name();
				m_file_path = path / name;
				name = convert_to_native(m_file_path.string());

				// 打开文件, 直接从文件读取数据.
				if (!m_file.is_open())
				{
					m_file.open(name.c_str(), std::ios::in | std::ios::binary);
					if (!m_file.is_open())
						return ret;
				}
			}

			if (!m_file.is_open())
				return ret;

            m_file.clear();
            m_file.seekg(offset, std::ios::beg);
            m_file.read(data, size);
            read_size = m_file.gcount();

			if (read_size != -1)
				ret = true;
		}

#if defined(_DEBUG) && defined(WIN32)
		static unsigned int cur_time = GetTickCount();
			char str_info[8192] = { 0 };
			char *ptr = (char*)str_info;
		if (GetTickCount() - cur_time >= 5000)
		{
			cur_time = GetTickCount();
			sprintf(str_info, "request: %d, size: %d, request time: %d, peers: %d\n", 
				index, (int)size, cur_time - time, status.num_peers);
			ptr = ptr + strlen(str_info);
			for (int i = 0; i < status.pieces.size() / 8; i++)
			{
				if (i % 32 == 0)
				{
					sprintf(ptr, "\n");
					ptr += 1;
				}
				sprintf(ptr, "%02X", (unsigned char)status.pieces.bytes()[i]);
				ptr += 2;
			}
			if (status.pieces.size() % 8 != 0)
			{
				sprintf(ptr, "%02X", (unsigned char)status.pieces.bytes()[status.pieces.size() / 8]);
				ptr += 2;
			}

			sprintf(ptr, "\n\n");

			// 显示当前正在下载的分片信息.
			std::string out;
			char str[500];
			std::vector<cached_piece_info> pieces;
			torrent_handle &h = m_handle;
			std::vector<partial_piece_info> queue;
			std::vector<peer_info> peers;

			m_ses.get_cache_info(h.info_hash(), pieces);
			h.get_download_queue(queue);
			h.get_peer_info(peers);

			std::sort(queue.begin(), queue.end(), boost::bind(&partial_piece_info::piece_index, _1)
				< boost::bind(&partial_piece_info::piece_index, _2));

			std::sort(pieces.begin(), pieces.end(), boost::bind(&cached_piece_info::last_use, _1)
				> boost::bind(&cached_piece_info::last_use, _2));

			for (std::vector<cached_piece_info>::iterator i = pieces.begin();
				i != pieces.end(); ++i)
			{
				partial_piece_info* pp = 0;
				partial_piece_info tmp;
				tmp.piece_index = i->piece;
				std::vector<partial_piece_info>::iterator ppi
					= std::lower_bound(queue.begin(), queue.end(), tmp
					, boost::bind(&partial_piece_info::piece_index, _1)
					< boost::bind(&partial_piece_info::piece_index, _2));
				if (ppi != queue.end() && ppi->piece_index == i->piece) pp = &*ppi;

				print_piece(pp, &*i, peers, out);

					if (pp) queue.erase(ppi);
			}

			for (std::vector<partial_piece_info>::iterator i = queue.begin()
				 , end(queue.end()); i != end; ++i)
			{
					print_piece(&*i, 0, peers, out);
			}
			snprintf(str, sizeof(str), "%s %s: read cache %s %s: downloading %s %s: cached %s %s: flushed\n"
				, esc("34;7"), esc("0") // read cache
				, esc("33;7"), esc("0") // downloading
				, esc("36;7"), esc("0") // cached
				, esc("32;7"), esc("0")); // flushed
			out += str;
			out += "___________________________________\n";

			strcat(str_info, out.c_str());

			OutputDebugStringA(str_info);
			printf(str_info);
		}
#endif

		return ret;
	}
Example #9
0
	void copy_file(std::string const& inf, std::string const& newf, error_code& ec)
	{
		ec.clear();
#if TORRENT_USE_WSTRING && defined TORRENT_WINDOWS
#define CopyFile_ CopyFileW
		std::wstring f1 = convert_to_wstring(inf);
		std::wstring f2 = convert_to_wstring(newf);
#else
#define CopyFile_ CopyFileA
		std::string f1 = convert_to_native(inf);
		std::string f2 = convert_to_native(newf);
#endif

#ifdef TORRENT_WINDOWS
		if (CopyFile_(f1.c_str(), f2.c_str(), false) == 0)
			ec.assign(GetLastError(), boost::system::get_system_category());
#elif defined __APPLE__ && defined __MACH__ && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
		// this only works on 10.5
		copyfile_state_t state = copyfile_state_alloc();
		if (copyfile(f1.c_str(), f2.c_str(), state, COPYFILE_ALL) < 0)
			ec.assign(errno, boost::system::get_generic_category());
		copyfile_state_free(state);
#else
		int infd = ::open(inf.c_str(), O_RDONLY);
		if (infd < 0)
		{
			ec.assign(errno, boost::system::get_generic_category());
			return;
		}

		// rely on default umask to filter x and w permissions
		// for group and others
		// TODO: copy the mode from the source file
		int permissions = S_IRUSR | S_IWUSR
			| S_IRGRP | S_IWGRP
			| S_IROTH | S_IWOTH;

		int outfd = ::open(newf.c_str(), O_WRONLY | O_CREAT, permissions);
		if (outfd < 0)
		{
			close(infd);
			ec.assign(errno, boost::system::get_generic_category());
			return;
		}
		char buffer[4096];
		for (;;)
		{
			int num_read = read(infd, buffer, sizeof(buffer));
			if (num_read == 0) break;
			if (num_read < 0)
			{
				ec.assign(errno, boost::system::get_generic_category());
				break;
			}
			int num_written = write(outfd, buffer, num_read);
			if (num_written < num_read)
			{
				ec.assign(errno, boost::system::get_generic_category());
				break;
			}
			if (num_read < int(sizeof(buffer))) break;
		}
		close(infd);
		close(outfd);
#endif // TORRENT_WINDOWS
	}
Example #10
0
bool torrent_source::open(boost::any ctx)
{
	// 保存打开指针.
	m_open_data.reset(boost::any_cast<open_torrent_data*>(ctx));

	// 开启下载对象.
	add_torrent_params p;

	p.save_path = m_open_data->save_path;
	error_code ec;

	// 打开种子, 开始下载.
	if (m_open_data->is_file)
	{
		p.ti = new torrent_info(m_open_data->filename, ec);
		if (ec)
		{
			printf("%s\n", ec.message().c_str());
			return false;
		}
	}

	// 非文件的种子, 直接使用种子数据打开torrent.
	if (!m_open_data->is_file)
	{
		p.ti = new torrent_info((const char*)m_open_data->torrent_data.get(), 
			m_open_data->data_size, ec);
		if (ec)
		{
			printf("%s\n", ec.message().c_str());
			return false;
		}
	}

	int index = 0;
	// 遍历视频文件.
	const file_storage &fs = p.ti->files();
	for (file_storage::iterator i = fs.begin();
		i != fs.end(); i++)
	{
		boost::filesystem::path p(convert_to_native(i->filename()));
		std::string ext = p.extension().string();
		if (ext == ".rmvb" ||
			ext == ".wmv" ||
			ext == ".avi" ||
			ext == ".mkv" ||
			ext == ".flv" ||
			ext == ".rm" ||
			ext == ".mp4" ||
			ext == ".3gp" ||
			ext == ".webm" ||
			ext == ".mpg")
		{
			video_file_info vfi;
			vfi.filename = convert_to_native(i->filename());
			vfi.base_offset = i->offset;
			vfi.offset = i->offset;
			vfi.data_size = i->size;
			vfi.index = index++;
			vfi.status = 0;

			// 当前视频默认置为第一个视频.
			if (m_current_video.index == -1)
				m_current_video = vfi;

			// 保存到视频列表中.
			m_videos.push_back(vfi);
		}
	}

	m_session.add_dht_router(std::make_pair(
		std::string("router.bittorrent.com"), 6881));
	m_session.add_dht_router(std::make_pair(
		std::string("router.utorrent.com"), 6881));
	m_session.add_dht_router(std::make_pair(
		std::string("router.bitcomet.com"), 6881));

	m_session.start_dht();

	//    m_session.load_asnum_db("GeoIPASNum.dat");
	//    m_session.load_country_db("GeoIP.dat");

	m_session.listen_on(std::make_pair(6881, 6889));

	// 设置缓冲.
	session_settings settings = m_session.settings();
	settings.use_read_cache = false;
	settings.disk_io_read_mode = session_settings::disable_os_cache;
	settings.broadcast_lsd = true;
	settings.allow_multiple_connections_per_ip = true;
	settings.local_service_announce_interval = 15;
	settings.min_announce_interval = 20;
	m_session.set_settings(settings);

	// 添加到session中.
	m_torrent_handle = m_session.add_torrent(p, ec);
	if (ec)
	{
		printf("%s\n", ec.message().c_str());
		return false;
	}

	m_torrent_handle.force_reannounce();

	// 自定义播放模式下载.
	m_torrent_handle.set_user_defined_download(true);

	// 限制上传速率为测试.
	// m_session.set_upload_rate_limit(80 * 1024);
	// m_session.set_local_upload_rate_limit(80 * 1024);

	// 创建bt数据读取对象.
	m_read_op.reset(new extern_read_op(m_torrent_handle, m_session));
	m_abort = false;

	return true;
}