TCP server: first version v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Sat, 20 Aug 2022 01:18:06 +0200
branchv_0
changeset 28 f2697551bfd5
parent 27 e6e5780339bd
child 29 97fe991ad2cb
TCP server: first version
src/Socket.cpp
--- a/src/Socket.cpp	Sat Aug 20 00:20:03 2022 +0200
+++ b/src/Socket.cpp	Sat Aug 20 01:18:06 2022 +0200
@@ -217,6 +217,38 @@
 	}
 };
 
+class TCPServerSocket : public Socket {
+private:
+	AddressInfos::AddressInfo localAddress;
+	FD socket;
+public:
+
+	TCPServerSocket(AddressInfos::AddressInfo localAddress) : localAddress(localAddress), socket(::socket(localAddress.ai->ai_family, localAddress.ai->ai_socktype, localAddress.ai->ai_protocol)) {
+	}
+
+	static std::shared_ptr<Socket> open(const SocketOptions& options) {
+		auto socket = openClientSocket<TCPServerSocket>(options, SOCK_STREAM, IPPROTO_TCP);
+		auto ai = socket->localAddress.ai;
+		int reuseAddr = true;
+		check(::setsockopt(socket->socket.getFD(), SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof (reuseAddr)), "setsockopt SO_REUSEADDR");
+		check(::bind(socket->socket.getFD(), ai->ai_addr, ai->ai_addrlen), "bind");
+		check(::listen(socket->socket.getFD(), 10), "listen"); // TODO: configurable backlog connection count?
+		return socket;
+	}
+
+	void send(const OutgoingMessage& message) override {
+		FD clientSocket(accept(socket.getFD(), nullptr, 0));
+		ssize_t written = ::write(clientSocket.getFD(), message.data.c_str(), message.data.size());
+		if (written != message.data.size()) throw std::logic_error("writing to the socket failed");
+		// TODO: partial writes, repeat
+	}
+
+	const IncomingMessage receive() override {
+		// TODO: TCP receive()
+		return IncomingMessage("TODO: receive() a message");
+	}
+};
+
 class SCTPClientSocket : public MSGSocket {
 private:
 	AddressInfos::AddressInfo remoteAddress;
@@ -298,11 +330,11 @@
 static std::vector<std::shared_ptr<SocketFactory>> factories
 {
 	std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_CLIENT, MODE_STREAM, TCPClientSocket >> (),
-	std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_SERVER, MODE_STREAM, TCPClientSocket >> (), // TODO: correct class
+	std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_SERVER, MODE_STREAM, TCPServerSocket >> (),
 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (),
 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
 	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_STREAM, SCTPClientSocket >> (),
-	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: do we need a stream-mode SCTP?
+	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_STREAM, UDSClientSocket >> (),
 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_DATAGRAM, UDSClientSocket >> (), // TODO: correct class
 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_STREAM, UDSClientSocket >> (), // TODO: correct class