Exemplo n.º 1
0
static Cbvalue parse_trackers(const std::string& v)
{
	Cbvalue announce_list;
	for (size_t i = 0; i < v.length(); )
	{
		int j = v.find_first_of("\t\n\r ", i);
		if (i == j)
		{
			i++;
			continue;
		}
		if (j == std::string::npos)
			j = v.length();
		std::string url = v.substr(i, j - i);
		announce_list.l(Cbvalue().l(url));
		i = j + 1;
	}
	return announce_list;
}
Exemplo n.º 2
0
void Cdlg_make_torrent::OnSave()
{
	if (!UpdateData())
		return;
	m_name.TrimRight(" ");
	m_tracker.TrimRight(" ");
	CFileDialog dlg(false, "torrent", m_name + ".torrent", OFN_ENABLESIZING | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST, "Torrents|*.torrent|", this);
	if (IDOK != dlg.DoModal())
		return;
	CWaitCursor wc;
	AfxGetApp()->WriteProfileString(m_strRegStore, "tracker", m_tracker);
	AfxGetApp()->WriteProfileString(m_strRegStore, "trackers", m_trackers);
	AfxGetApp()->WriteProfileInt(m_strRegStore, "use_merkle", m_use_merkle);
	int cb_piece = 1 << 20;
	if (!m_use_merkle)
	{
		long long cb_total = 0;
		for (t_map::const_iterator i = m_map.begin(); i != m_map.end(); i++)
			cb_total += i->second.size;
		cb_piece = 256 << 10;
		while (cb_total / cb_piece > 4 << 10)
			cb_piece <<= 1;
	}
	typedef std::set<std::string> t_set;
	t_set set;
	for (t_map::const_iterator i = m_map.begin(); i != m_map.end(); i++)
		set.insert(i->second.name);
	Cbvalue files;
	std::string pieces;
	Cvirtual_binary d;
	byte* w = d.write_start(cb_piece);
	for (t_set::const_iterator i = set.begin(); i != set.end(); i++)
	{
		int f = open(i->c_str(), _O_BINARY | _O_RDONLY);
		if (!f)
			continue;
		long long cb_f = 0;
		std::string merkle_hash;
		int cb_d;
		if (m_use_merkle)
		{
			typedef std::map<int, std::string> t_map;

			t_map map;
			char d[1025];
			while (cb_d = read(f, d + 1, 1024))
			{
				if (cb_d < 0)
					break;
				*d = 0;
				std::string h = Csha1(const_memory_range(d, cb_d + 1)).read();
				*d = 1;
				int i;
				for (i = 0; map.find(i) != map.end(); i++)
				{
					memcpy(d + 1, map.find(i)->second.c_str(), 20);
					memcpy(d + 21, h.c_str(), 20);
					h = Csha1(const_memory_range(d, 41)).read();
					map.erase(i);
				}
				map[i] = h;
				cb_f += cb_d;
			}
			*d = 1;
			while (map.size() > 1)
			{
				memcpy(d + 21, map.begin()->second.c_str(), 20);
				map.erase(map.begin());
				memcpy(d + 1, map.begin()->second.c_str(), 20);
				map.erase(map.begin());
				map[0] = Csha1(const_memory_range(d, 41)).read();
			}
			if (!map.empty())
				merkle_hash = map.begin()->second;
		}
		else
		{
			while (cb_d = read(f, w, d.end() - w))
			{
				if (cb_d < 0)
					break;
				w += cb_d;
				if (w == d.end())
				{
					pieces += Csha1(const_memory_range(d, w - d)).read();
					w = d.data_edit();
				}
				cb_f += cb_d;
			}
		}
		close(f);
		files.l(merkle_hash.empty()
			? Cbvalue().d(bts_length, cb_f).d(bts_path, Cbvalue().l(base_name(*i)))
			: Cbvalue().d(bts_merkle_hash, merkle_hash).d(bts_length, cb_f).d(bts_path, Cbvalue().l(base_name(*i))));
	}
	if (w != d)
		pieces += Csha1(const_memory_range(d, w - d)).read();
	Cbvalue info;
	info.d(bts_piece_length, cb_piece);
	if (!pieces.empty())
		info.d(bts_pieces, pieces);
	if (m_map.size() == 1)
	{
		if (m_use_merkle)
			info.d(bts_merkle_hash, files.l().front()[bts_merkle_hash]);
		info.d(bts_length, files.l().front()[bts_length]);
		info.d(bts_name, files.l().front()[bts_path].l().front());
	}
	else
	{
		info.d(bts_files, files);
		info.d(bts_name, static_cast<std::string>(m_name));
	}
	Cbvalue torrent;
	torrent.d(bts_announce, static_cast<std::string>(m_tracker));
	if (!m_trackers.IsEmpty())
		torrent.d(bts_announce_list, parse_trackers(static_cast<std::string>(m_trackers)));
	torrent.d(bts_info, info);
	Cvirtual_binary s = torrent.read();
	if (m_use_merkle)
		s = gzip(s);
	s.save(static_cast<std::string>(dlg.GetPathName()));
	m_torrent_fname = dlg.GetPathName();
	EndDialog(IDOK);
}
Exemplo n.º 3
0
void Cconnection::read(const std::string& v)
{
#ifndef NDEBUG
	std::cout << v << std::endl;
#endif
	if (m_server->config().m_log_access)
	{
		static std::ofstream f("xbt_tracker_raw.log");
		f << m_server->time() << '\t' << inet_ntoa(m_a.sin_addr) << '\t' << ntohs(m_a.sin_port) << '\t' << v << std::endl;
	}
	Ctracker_input ti;
	size_t e = v.find('?');
	if (e == std::string::npos)
		e = v.size();
	else
	{
		size_t a = e + 1;
		size_t b = v.find(' ', a);
		if (b == std::string::npos)
			return;
		while (a < b)
		{
			size_t c = v.find('=', a);
			if (c++ == std::string::npos)
				break;
			size_t d = v.find_first_of(" &", c);
			if (d == std::string::npos)
				break;
			ti.set(v.substr(a, c - a - 1), uri_decode(v.substr(c, d - c)));
			a = d + 1;
		}
	}
	if (!ti.m_ipa || !is_private_ipa(m_a.sin_addr.s_addr))
		ti.m_ipa = m_a.sin_addr.s_addr;
	std::string torrent_pass0;
	size_t a = 4;
	if (a < e && v[a] == '/')
	{
		a++;
		if (a + 1 < e && v[a + 1] == '/')
			a += 2;
		if (a + 32 < e && v[a + 32] == '/')
		{
			torrent_pass0 = v.substr(a, 32);
			a += 33;
			if (a + 40 < e && v[a + 40] == '/')
				a += 41;
		}
	}
	std::string h = "HTTP/1.0 200 OK\r\n";
	Cvirtual_binary s;
	bool gzip = true;
	switch (a < v.size() ? v[a] : 0)
	{
	case 'a':
		if (!ti.valid())
			break;
		gzip = false;
		if (0)
			s = Cbvalue().d(bts_failure_reason, bts_banned_client).read();
		else
		{
			std::string error = m_server->insert_peer(ti, false, m_server->find_user_by_torrent_pass(torrent_pass0, ti.m_info_hash));
			s = error.empty() ? m_server->select_peers(ti) : Cbvalue().d(bts_failure_reason, error).read();
		}
		break;
	case 'd':
		if (m_server->config().m_debug)
		{
			gzip = m_server->config().m_gzip_debug;
			h += "Content-Type: text/html; charset=us-ascii\r\n";
			s = Cvirtual_binary(m_server->debug(ti));
		}
		break;
	case 's':
		if (v.size() >= 7 && v[6] == 't')
		{
			gzip = m_server->config().m_gzip_debug;
			h += "Content-Type: text/html; charset=us-ascii\r\n";
			s = Cvirtual_binary(m_server->statistics());
		}
		else if (m_server->config().m_full_scrape || ti.m_compact || !ti.m_info_hash.empty())
		{
			gzip = m_server->config().m_gzip_scrape && !ti.m_compact && ti.m_info_hash.empty();
			s = m_server->scrape(ti);
		}
		break;
	}
	if (s.empty())
	{
		if (!ti.m_peer_id.empty() || m_server->config().m_redirect_url.empty())
			h = "HTTP/1.0 404 Not Found\r\n";
		else
		{
			h = "HTTP/1.0 302 Found\r\n"
				"Location: " + m_server->config().m_redirect_url + (ti.m_info_hash.empty() ? "" : "?info_hash=" + uri_encode(ti.m_info_hash)) + "\r\n";
		}
	}
	else if (gzip)
	{
		Cvirtual_binary s2 = xcc_z::gzip(s);
#ifndef NDEBUG
		static std::ofstream f("xbt_tracker_gzip.log");
		f << m_server->time() << '\t' << v[5] << '\t' << s.size() << '\t' << s2.size() << std::endl;
#endif
		if (s2.size() + 24 < s.size())
		{
			h += "Content-Encoding: gzip\r\n";
			s = s2;
		}
	}
	h += "\r\n";
#ifdef WIN32
	m_write_b.resize(h.size() + s.size());
	memcpy(m_write_b.data_edit(), h.data(), h.size());
	s.read(m_write_b.data_edit() + h.size());
	int r = m_s.send(m_write_b);
#else
	boost::array<iovec, 2> d;
	d[0].iov_base = const_cast<char*>(h.data());
	d[0].iov_len = h.size();
	d[1].iov_base = const_cast<unsigned char*>(s.data());
	d[1].iov_len = s.size();
	msghdr m;
	m.msg_name = NULL;
	m.msg_namelen = 0;
	m.msg_iov = const_cast<iovec*>(d.data());
	m.msg_iovlen = d.size();
	m.msg_control = NULL;
	m.msg_controllen = 0;
	m.msg_flags = 0;
	int r = sendmsg(m_s, &m, MSG_NOSIGNAL);
#endif
	if (r == SOCKET_ERROR)
	{
		if (WSAGetLastError() != WSAECONNRESET)
			std::cerr << "send failed: " << Csocket::error2a(WSAGetLastError()) << std::endl;
	}
	else if (r != h.size() + s.size())
	{
#ifndef WIN32
		if (r < h.size())
		{
			m_write_b.resize(h.size() + s.size());
			memcpy(m_write_b.data_edit(), h.data(), h.size());
			s.read(m_write_b.data_edit() + h.size());
		}
		else
		{
			m_write_b = s;
			r -= h.size();
		}
#endif
		m_r = m_write_b;
		m_r += r;
	}
	if (m_r.empty())
		m_write_b.clear();
}
Exemplo n.º 4
0
int main(int argc, char* argv[])
{
	time_t t = time(NULL);
	if (argc < 2)
	{
		std::cerr << "Usage: " << argv[0] << " <file> <tracker> [--v1]" << std::endl;
		return 1;
	}
	std::string tracker = argc >= 3 ? argv[2] : "udp://localhost:2710";
	bool use_merkle = argc >= 4 ? strcmp(argv[3], "--v1") : true; // set to false for a non-merkle torrent
	insert(argv[1]);
	// use 1 mbyte pieces by default
	int cb_piece = 1 << 20;
	if (!use_merkle)
	{
		// find optimal piece size for a non-merkle torrent
		long long cb_total = 0;
		for (t_map::const_iterator i = g_map.begin(); i != g_map.end(); i++)
			cb_total += i->second.size;
		cb_piece = 256 << 10;
		while (cb_total / cb_piece > 4 << 10)
			cb_piece <<= 1;
	}
	Cbvalue files;
	std::string pieces;
	Cvirtual_binary d;
	byte* w = d.write_start(cb_piece);
	for (t_map::const_iterator i = g_map.begin(); i != g_map.end(); i++)
	{
		int f = open(i->second.name.c_str(), O_BINARY | O_RDONLY);
		if (!f)
			continue;
		long long cb_f = 0;
		std::string merkle_hash;
		int cb_d;
		if (use_merkle)
		{
			// calculate merkle root hash as explained in XBT Make Merkle Tree.cpp
			typedef std::map<int, std::string> t_map;

			t_map map;
			char d[1025];
			while (cb_d = read(f, d + 1, 1024))
			{
				if (cb_d < 0)
					break;
				*d = 0;
				std::string h = Csha1(const_memory_range(d, cb_d + 1)).read();
				*d = 1;
				int i;
				for (i = 0; map.find(i) != map.end(); i++)
				{
					memcpy(d + 1, map.find(i)->second.c_str(), 20);
					memcpy(d + 21, h.c_str(), 20);
					h = Csha1(const_memory_range(d, 41)).read();
					map.erase(i);
				}
				map[i] = h;
				cb_f += cb_d;
			}
			*d = 1;
			while (map.size() > 1)
			{
				memcpy(d + 21, map.begin()->second.c_str(), 20);
				map.erase(map.begin());
				memcpy(d + 1, map.begin()->second.c_str(), 20);
				map.erase(map.begin());
				map[0] = Csha1(const_memory_range(d, 41)).read();
			}
			if (!map.empty())
				merkle_hash = map.begin()->second;
		}
		else
		{
			// calculate piece hashes
			while (cb_d = read(f, w, d.data_end() - w))
			{
				if (cb_d < 0)
					break;
				w += cb_d;
				if (w == d.data_end())
				{
					pieces += Csha1(const_memory_range(d, w - d)).read();
					w = d.data_edit();
				}
				cb_f += cb_d;
			}
		}
		close(f);
		// add file to files key
		files.l(merkle_hash.empty()
			? Cbvalue().d(bts_length, cb_f).d(bts_path, Cbvalue().l(base_name(i->second.name)))
			: Cbvalue().d(bts_merkle_hash, merkle_hash).d(bts_length, cb_f).d(bts_path, Cbvalue().l(base_name(i->second.name))));
	}
	if (w != d)
		pieces += Csha1(const_memory_range(d, w - d)).read();
	Cbvalue info;
	info.d(bts_piece_length, cb_piece);
	if (!pieces.empty())
		info.d(bts_pieces, pieces);
	if (g_map.size() == 1)
	{
		// single-file torrent
		if (use_merkle)
			info.d(bts_merkle_hash, files.l().front().d(bts_merkle_hash));
		info.d(bts_length, files.l().front().d(bts_length));
		info.d(bts_name, files.l().front().d(bts_path).l().front());
	}
	else
	{
		// multi-file torrent
		info.d(bts_files, files);
		info.d(bts_name, g_name);
	}
	Cbvalue torrent;
	torrent.d(bts_announce, tracker);
	torrent.d(bts_info, info);
	Cvirtual_binary s = torrent.read();
	if (use_merkle)
		s = gzip(s);
	s.save(g_name + ".torrent");
	std::cout << time(NULL) - t << " s" << std::endl;
	return 0;
}