Example #1
0
typename T2::iterator copy_safe_apart(size_t n, const T1 & tab_src, T2 & tab_dst, size_t offset_src=0, size_t offset_dst=0) {
	_dbg5("copy (tab) n="<<n);
	if (n<1) return tab_dst.begin();

	// could write both blocks below with lambda, in C++17TODO when decomposition declarations is available

	// source
	auto src_rb = tab_src.begin() + offset_src; // rb = range begin
	_check_input( offset_src < tab_src.size() );
	_check_input( n <= tab_src.size() - offset_src ); // subtracting offset_src is valid since above
	auto src_rl = tab_src.begin() + offset_src + n -1; // range last
	_dbg5("Source     range src_rb="<<to_debug(src_rb)<<" ... src_rl="<<to_debug(src_rl));
	_check_abort( src_rl <= tab_src.end() );

	// dest
	auto dst_rb = tab_dst.begin() + offset_dst; // rb = range begin
	_check_input( offset_dst < tab_dst.size() );
	_check_input( n <= tab_dst.size() - offset_dst ); // subtracting offset_dst is valid since above
	auto dst_rl = tab_dst.begin() + offset_dst + n -1; // range last
	_dbg5("Destintion range dst_rb="<<to_debug(dst_rb)<<" ... dst_rl="<<to_debug(dst_rl));
	_check_abort( dst_rl <= tab_dst.end() );

	bool overlap = test_ranges_overlap_inclusive_noempty(src_rb, src_rl,  dst_rb, dst_rl);
	_dbg5("overlap=" << overlap);
	_check_input(!overlap);

	copy_iter_and_check_no_overlap( src_rb, src_rl,  dst_rb, n );
	_dbg5("Copy done.");

	return dst_rb;
}
size_t c_tuntap_linux_obj::send_to_tun_separated_addresses(const unsigned char *const data, size_t size,
	const std::array<unsigned char, IPV6_LEN> &src_binary_address,
	const std::array<unsigned char, IPV6_LEN> &dst_binary_address) {
	_check_input(size >= 8);
	std::array<boost::asio::const_buffer, 4> buffers;
	buffers.at(0) = boost::asio::buffer(data, 8); // version, traffic, flow label, payload length, next header, hop limit
	buffers.at(1) = boost::asio::buffer(src_binary_address.data(), src_binary_address.size());
	buffers.at(2) = boost::asio::buffer(dst_binary_address.data(), dst_binary_address.size());
	buffers.at(3) = boost::asio::buffer(data + 8, size - 8); // 8 bytes are filled in buffers.at(0)
	boost::system::error_code ec;
	return m_tun_stream.write_some(buffers, ec);
}
void c_tuntap_linux_obj::set_tun_parameters(const std::array<unsigned char, IPV6_LEN> &binary_address,
                                            int prefix_len,
                                            uint32_t mtu) {

	c_haship_addr address(c_haship_addr::tag_constr_by_array_uchar(), binary_address);
	_goal("Configuring tuntap options: IP address: " << address << "/" << prefix_len << " MTU=" << mtu);
	as_zerofill< ifreq > ifr; // the if request
	ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
	strncpy(ifr.ifr_name, "galaxy%d", IFNAMSIZ);
	int errcode_ioctl = sys_fun.ioctl(m_tun_fd, TUNSETIFF, static_cast<void *>(&ifr));
	_check_sys(errcode_ioctl != -1);
	_check_input(binary_address[0] == 0xFD);
	_check_input(binary_address[1] == 0x42);
	t_syserr err;
	err = sys_fun.NetPlatform_addAddress(ifr.ifr_name, binary_address.data(), prefix_len, Sockaddr_AF_INET6);
	if (err.my_code != 0) throw std::runtime_error("NetPlatform_addAddress error");
	err = sys_fun.NetPlatform_setMTU(ifr.ifr_name, mtu);
	if (err.my_code != 0) throw std::runtime_error("NetPlatform_setMTU error");
	m_tun_stream.release();
	m_tun_stream.assign(m_tun_fd);
	_goal("Configuring tuntap options - done");
}
size_t c_tuntap_linux_obj::read_from_tun_separated_addresses(unsigned char *const data, size_t size,
	std::array<unsigned char, IPV6_LEN> &src_binary_address,
	std::array<unsigned char, IPV6_LEN> &dst_binary_address) {
	_check_input(size >= 8);
	// field sizes based on rfc2460
	// https://tools.ietf.org/html/rfc2460
	std::array<boost::asio::mutable_buffer, 4> buffers;
	buffers.at(0) = boost::asio::buffer(data, 8); // version, traffic, flow label, payload length, next header, hop limit
	buffers.at(1) = boost::asio::buffer(src_binary_address.data(), src_binary_address.size());
	buffers.at(2) = boost::asio::buffer(dst_binary_address.data(), dst_binary_address.size());
	buffers.at(3) = boost::asio::buffer(data + 8, size - 8); // 8 bytes are filled in buffers.at(0)
	try {
		return m_tun_stream.read_some(buffers) - src_binary_address.size() - dst_binary_address.size();
	} catch (const std::exception &) {
		return 0;
	}
}
c_galaxysrv_peers::t_peering_reference_parse c_galaxysrv_peers::parse_peer_reference(const string & simple) const{
	// @TODO not using std::regex since it had compatibility problems. Consider using when possible (bug#J446).
	const char separator='@', group_open='(', group_close=')';
	const string literal_anyone = "anyone";
	reasonable_size(simple);

	_note("Parsing: "<<simple);
	_check_input(simple.size()>=3); // some reasonable sized not-empty string

	size_t pos1 = simple.find(separator); // was there any "@"

	if (pos1 == string::npos) { // must be one-part format "VIRTUAL" (only contains the ID/ipv6, no cables)
		vector<string> ret_id( { simple } ); // e.g. "fd42:f6c4:9d19:f128:30df:b289:aef0:25f5,score=-300"
		vector<string> ret_cable{ };
		// make sure this part does not contain ( or ) etc
		_check_input( string::npos == simple.find(group_open) );
		_check_input( string::npos == simple.find(group_close) );
		_check_input( simple.size()>0 );
		return std::make_pair(std::move(ret_id), std::move(ret_cable));
	}
	else { // format "VIRTUAL@(CABLE)" possibly with more "@(CABLE)"
		string part1 = simple.substr(0,pos1); // the VIRTUAL
		// make sure this part does not contain ( or )
		_check_input( string::npos == part1.find(group_open) );
		_check_input( string::npos == part1.find(group_close) );
		_check_input( part1.size()>0 );
		vector<string> ret_id;
		if (part1 != literal_anyone) {
			ret_id.push_back( part1 ); // e.g. "fd42:f6c4:9d19:f128:30df:b289:aef0:25f5,score=-300"
		} // else, it is 'anyone' VIRTUAL - so it is reported by empty string

		// fd42::25f5@(udp:p.meshnet.pl:9042,cost=500)@(shm:test)@(tcp:[fe80::d44e]:9042)
		//             B
		//             B.............................X
		//                                           X@(B
		//                                              B.......X@
		//                                                      X@(B
		//                                                         B.....................end

		vector<string> ret_cable;
		// will parse additional groups "@(....)" selecting their index posB...posX
		const size_t size = simple.size(), size_before=size-1; _check(size_before < size);
		_check_input(pos1+2 < size);
		_check_input(simple.at(pos1+0)==separator);  // theck the '@' out of "@(" that we just found
		_check_input(simple.at(pos1+1)==group_open); // theck the '(' out of "@(" that we just found
		size_t posB = pos1+2; // begin, poiting after "@("
		_info(join_string_sep(posB," < ",size));
		while (posB < size_before) {
			auto posX = simple.find(group_close,posB); // find ")"
			_dbg3("posX=" << posX << " posB="<<posB);
			if (posX == string::npos) {
				_info("Hit end because posX="<<posX);
				posX = size_before;
			}
			string partX = simple.substr(posB, posX-posB);
			_dbg3("posX=" << posX << " posB="<<posB<<" given " <<partX);
			// make sure this part does not contain ( or ), e.g. "CABLE(" as result of parsing "VIRTUAL@(CABLE(CABLE)"
			_check_input( string::npos == partX.find(group_open) );
			_check_input( string::npos == partX.find(group_close) );
			_check_input( partX.size()>0 );

			ret_cable.push_back( std::move(partX) );
			posB=posX;
			_check_input(simple.at(posB)==group_close); // ")"
			++posB;
			if (!(posB<size)) break; // end is possible after last "....@(...)"
			// otherwise we open new group:
			_check_input(simple.at(posB)==separator); // ")@"
			++posB;
			_check_input(simple.at(posB)==group_open); // ")@(" after this
			++posB;
		}
		return std::make_pair(std::move(ret_id), std::move(ret_cable));
	} // other format
}
Example #6
0
/******************************************************************************
// Read user input from standard in
// Input:
// Output:
// n: number of cities
// adjMtx: the adjacency matrix, note the memory should be freed later
// Return:
// 1 success; 0 failed alloc memory
******************************************************************************/
int read_input(int *n, int **adjMtx)
{
	int i;
	int value;
	int idx = 0;
	int cnt = 0;
	int sz = INT_MAX;
	char str[SIZE]; //possible overflow

	//read number of cities
	while (1)
	{
		printf("please input the cities:\n");
		scanf("%s", str);

		sz = INT_MAX;
		if (_isalldigit(str) == 1)
		{
			sz = _atoi(str);
		}
		//the first parameter should be a number between min cities and max cities
		if (sz <= MIN_CITIES || sz >= MAX_CITIES)
		{
			printf("first parameter %s isn't in [%d, %d]\n", str, MIN_CITIES, MAX_CITIES);
		}
		else
		{
			break;
		}
	}
	//init number of cities
	*n = sz;
	
	//build adjMtx
	*adjMtx = (int*)malloc(sz*sz*sizeof(int));
	if (*adjMtx == NULL)
	{
		printf("not enough memory\n");
		return 0;
	}

	//read other inputs
	while (++idx < sz)
	{
		while (1)
		{
			printf("please input [%d] elements for [%d]th line of half matrix:\n", idx, idx);
			cnt = 0;
			i = idx;
			while (i--)
			{
				scanf("%s", str);
				if (_check_input(str) == 0)
				{
					printf("input must be a number without sign or character x: %s\n", str);
					scanf("%*[^\n]"); //discard other inputs in this line if error occurs
					break;
				}
				else
				{
					value = _inputtoi(str);
					(*adjMtx)[idx*sz + cnt] = value; //A(i, j)
					(*adjMtx)[cnt*sz + idx] = value; //A(j, i)
					++cnt;
				}
			}
			if (cnt == idx) //inputs for this line are complete
			{
				scanf("%*[^\n]"); //discard more in the tail
				break;
			}
		}
	}
	//init diagnol matrix values
	for (i = 0; i < sz; ++i)
	{
		(*adjMtx)[i*sz + i] = 0;
	}

	//check all values
	//for (i = 0; i < sz * sz; ++i)
	//{
	//	printf("%d\t", (*adjMtx)[i]);
	//	if ((i+1)%sz == 0)
	//		printf("\n");
	//}

	return 1;
}