UDS: first version v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Thu, 18 Aug 2022 18:08:39 +0200
branchv_0
changeset 24 b668bd88ffa2
parent 23 4d97d58d40df
child 25 de58479757e1
UDS: first version
src/Socket.cpp
--- a/src/Socket.cpp	Thu Aug 18 03:43:19 2022 +0200
+++ b/src/Socket.cpp	Thu Aug 18 18:08:39 2022 +0200
@@ -21,6 +21,7 @@
 #include <arpa/inet.h>
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/un.h>
 #include <netinet/in.h>
 #include <vector>
 #include <memory>
@@ -134,6 +135,17 @@
 	return std::shared_ptr<SocketClass>(new SocketClass(remoteAddresses[0], moreArgs...));
 }
 
+void sendmsg(int fd, const std::string& message) {
+	iovec iov[1];
+	msghdr msg = {};
+	msg.msg_iov = iov;
+	msg.msg_iov[0].iov_base = (void*) message.c_str();
+	msg.msg_iov[0].iov_len = message.size();
+	msg.msg_iovlen = sizeof (iov) / sizeof (iov[0]);
+	ssize_t written = ::sendmsg(fd, &msg, 0);
+	if (written != message.size()) throw std::logic_error("writing to the socket failed");
+}
+
 class UDPClientSocket : public Socket {
 private:
 	AddressInfos::AddressInfo remoteAddress;
@@ -208,14 +220,7 @@
 	}
 
 	void send(const std::string& message) override {
-		iovec iov[1];
-		msghdr msg = {};
-		msg.msg_iov = iov;
-		msg.msg_iov[0].iov_base = (void*) message.c_str();
-		msg.msg_iov[0].iov_len = message.size();
-		msg.msg_iovlen = sizeof (iov) / sizeof (iov[0]);
-		ssize_t written = ::sendmsg(socket.getFD(), &msg, 0);
-		if (written != message.size()) throw std::logic_error("writing to the socket failed");
+		sendmsg(socket.getFD(), message);
 	}
 
 	const std::string receive() override {
@@ -224,6 +229,60 @@
 	}
 };
 
+class UDSClientSocket : public Socket {
+private:
+	FD socket;
+
+public:
+
+	UDSClientSocket(int fd) : socket(fd) {
+	}
+
+	static std::shared_ptr<Socket> open(const SocketOptions& options) {
+		struct sockaddr_un address;
+		std::string path = findOption(options, OPTION_PATH);
+
+		memset(&address, 0x00, sizeof (address));
+		address.sun_family = AF_UNIX;
+		strncpy(address.sun_path, path.c_str(), path.size());
+
+		int fd = ::socket(AF_UNIX, SOCK_STREAM, 0);
+
+		auto socket = std::make_shared<UDSClientSocket>(fd);
+		check(::connect(socket->socket.getFD(), (const sockaddr*) &address, sizeof (address)), "connect socket");
+
+
+		// zjistíme UID, GID a PID klienta, který se připojil na náš unixový soket:
+		struct ucred cr;
+		socklen_t crLen = sizeof (cr);
+		memset(&cr, 0x00, crLen);
+		getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &crLen);
+
+		// při opakovaném volání vrací stále totéž:
+		// memset(&cr, 0x00, sizeof (cr));
+		// getsockopt(spojeni, SOL_SOCKET, SO_PEERCRED, &cr, &crLen);
+
+		printf("Přijato spojení\n");
+		printf("  FD = %d\n", fd);
+		printf("  klientská cesta = %s\n", address.sun_path); // tohle je vždy prázdné
+		printf("  klientský PID = %d\n", cr.pid);
+		printf("  klientský UID = %d\n", cr.uid);
+		printf("  klientský GID = %d\n", cr.gid);
+
+
+		return socket;
+	}
+
+	void send(const std::string& message) override {
+		sendmsg(socket.getFD(), message);
+	}
+
+	const std::string receive() override {
+		// TODO: UDS receive()
+		return "TODO: receive() a message";
+	}
+};
+
 template<const char* protocol, const char* role, const char* mode, typename SocketClass>
 class TemplateSocketFactory : public SocketFactory {
 public:
@@ -249,10 +308,10 @@
 			std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_DATAGRAM, 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_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
-			std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
-			std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
-			std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
-			std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
+			std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_STREAM, UDSClientSocket >> (), // TODO: correct class
+			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
+			std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_DATAGRAM, UDSClientSocket >> (), // TODO: correct class
 };
 
 std::shared_ptr<SocketFactory> SocketFactory::find(const SocketOptions& options) {