示例#1
1
err_t socket_t::accept(socket_t* sd, std::string* ip, uint16_t* port, bool* ipv6) {
	struct sockaddr_storage addr;
	socklen_t len = sizeof(addr);
	char buf[INET6_ADDRSTRLEN + 1];

	assert(this->is_open());
	assert(sd != 0);
	assert(ip != 0);
	assert(port != 0);
	assert(ipv6 != 0);

	const auto result = ::accept(this->get(), (struct sockaddr*) &addr, &len);
	if (result < 0) {
		return err_t::current();
	}

	// Set return values.
	if (addr.ss_family == AF_INET) {
		const auto addr_v4 = (struct sockaddr_in*) &addr;

		if (inet_ntop(AF_INET, &addr_v4->sin_addr, buf, sizeof(buf)) == 0) {
			const auto e = err_t::current();
			::close(result);
			return e;
		}

		*ip = buf;
		*port = ntohs(addr_v4->sin_port);
		*ipv6 = false;

	} else if (addr.ss_family == AF_INET6) {
		const auto addr_v6 = (struct sockaddr_in6*) &addr;

		if (inet_ntop(AF_INET6, &addr_v6->sin6_addr, buf, sizeof(buf)) == 0) {
			const auto e = err_t::current();
			::close(result);
			return e;
		}

		*ip = buf;
		*port = ntohs(addr_v6->sin6_port);
		*ipv6 = true;

	} else {
		::close(result);
		return EINVAL;
	}

	*sd = result;
	return err_t();
}
示例#2
0
err_t socket_t::bind_ipv4(const std::string& ip, uint16_t port) {
	assert(this->is_open());

	struct sockaddr_in address;

	bzero(&address, sizeof(address));
	address.sin_family = AF_INET;
	address.sin_port = htons(port);

	if (!ip.empty()) {
		const int result = inet_pton(AF_INET, ip.c_str(), &address.sin_addr);
		if (result != 1) {
			if (result == 0) {
				return EINVAL;
			} else {
				return err_t::current();
			}
		}
	}

	auto ret = this->reuseaddr(true);
	if (!ret) {
		return ret;
	}

	if (bind(this->get(), (struct sockaddr*) &address, sizeof(address)) != 0) {
		return err_t::current();
	}

	return err_t();
}
示例#3
0
err_t socket_t::new_ipv6_nonblock() {
	this->set(socket(AF_INET6, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0));
	if (this->get() == -1) {
		return err_t::current();
	}

	return err_t();
}
示例#4
0
err_t socket_t::listen(int backlog) {
	assert(this->is_open());

	if (::listen(this->get(), backlog) != 0) {
		return err_t::current();
	}

	return err_t();
}
示例#5
0
err_t socket_t::reuseaddr(bool flag) {
	assert(this->is_open());

	const int state = flag ? 1 : 0;
	if (setsockopt(this->get(), SOL_SOCKET, SO_REUSEADDR,
			&state, (socklen_t) sizeof(state)) == -1) {
		return err_t::current();
	}

	return err_t();
}
示例#6
0
err_t socket_t::recv(void* buf, size_t size, size_t* ok_bytes) {
	assert(this->is_open());
	assert(buf != 0 || size == 0);
	assert(ok_bytes != 0);

	const auto result = ::recv(this->get(), buf, size, 0);
	if (result == -1) {
		*ok_bytes = 0;
		return err_t::current();
	} else {
		*ok_bytes = result;
		return err_t();
	}
}
示例#7
0
err_t socket_t::bind_ipv6(const std::string& ip, uint16_t port) {
	assert(this->is_open());

	// Make IPV6 accept IPV6 connections only.
	// Otherwise, listening to the same port would fail.
	int on = 1;
	if (setsockopt(this->get(), IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1) {
		return err_t::current();
	}

	struct sockaddr_in6 address;

	bzero(&address, sizeof(address));
	address.sin6_family = AF_INET6;
	address.sin6_port = htons(port);

	if (!ip.empty()) {
		const int result = inet_pton(AF_INET6, ip.c_str(), &address.sin6_addr);
		if (result != 1) {
			if (result == 0) {
				return EINVAL;
			} else {
				return err_t::current();
			}
		}
	}

	auto ret = this->reuseaddr(true);
	if (!ret) {
		return ret;
	}

	if (bind(this->get(), (struct sockaddr*) &address, sizeof(address)) != 0) {
		return err_t::current();
	}

	return err_t();
}
示例#8
0
 ~raise_t() { throw err_t(oss.str()); }