src/Socket.cpp
branchv_0
changeset 24 b668bd88ffa2
parent 23 4d97d58d40df
child 25 de58479757e1
equal deleted inserted replaced
23:4d97d58d40df 24:b668bd88ffa2
    19 #include <unistd.h>
    19 #include <unistd.h>
    20 #include <stdexcept>
    20 #include <stdexcept>
    21 #include <arpa/inet.h>
    21 #include <arpa/inet.h>
    22 #include <sys/types.h>
    22 #include <sys/types.h>
    23 #include <sys/socket.h>
    23 #include <sys/socket.h>
       
    24 #include <sys/un.h>
    24 #include <netinet/in.h>
    25 #include <netinet/in.h>
    25 #include <vector>
    26 #include <vector>
    26 #include <memory>
    27 #include <memory>
    27 #include <regex>
    28 #include <regex>
    28 #include <iostream>
    29 #include <iostream>
   132 			protocol);
   133 			protocol);
   133 
   134 
   134 	return std::shared_ptr<SocketClass>(new SocketClass(remoteAddresses[0], moreArgs...));
   135 	return std::shared_ptr<SocketClass>(new SocketClass(remoteAddresses[0], moreArgs...));
   135 }
   136 }
   136 
   137 
       
   138 void sendmsg(int fd, const std::string& message) {
       
   139 	iovec iov[1];
       
   140 	msghdr msg = {};
       
   141 	msg.msg_iov = iov;
       
   142 	msg.msg_iov[0].iov_base = (void*) message.c_str();
       
   143 	msg.msg_iov[0].iov_len = message.size();
       
   144 	msg.msg_iovlen = sizeof (iov) / sizeof (iov[0]);
       
   145 	ssize_t written = ::sendmsg(fd, &msg, 0);
       
   146 	if (written != message.size()) throw std::logic_error("writing to the socket failed");
       
   147 }
       
   148 
   137 class UDPClientSocket : public Socket {
   149 class UDPClientSocket : public Socket {
   138 private:
   150 private:
   139 	AddressInfos::AddressInfo remoteAddress;
   151 	AddressInfos::AddressInfo remoteAddress;
   140 	useconds_t delay = 0;
   152 	useconds_t delay = 0;
   141 	FD socket;
   153 	FD socket;
   206 		check(::connect(socket->socket.getFD(), socket->remoteAddress.ai->ai_addr, socket->remoteAddress.ai->ai_addrlen), "connect socket");
   218 		check(::connect(socket->socket.getFD(), socket->remoteAddress.ai->ai_addr, socket->remoteAddress.ai->ai_addrlen), "connect socket");
   207 		return socket;
   219 		return socket;
   208 	}
   220 	}
   209 
   221 
   210 	void send(const std::string& message) override {
   222 	void send(const std::string& message) override {
   211 		iovec iov[1];
   223 		sendmsg(socket.getFD(), message);
   212 		msghdr msg = {};
       
   213 		msg.msg_iov = iov;
       
   214 		msg.msg_iov[0].iov_base = (void*) message.c_str();
       
   215 		msg.msg_iov[0].iov_len = message.size();
       
   216 		msg.msg_iovlen = sizeof (iov) / sizeof (iov[0]);
       
   217 		ssize_t written = ::sendmsg(socket.getFD(), &msg, 0);
       
   218 		if (written != message.size()) throw std::logic_error("writing to the socket failed");
       
   219 	}
   224 	}
   220 
   225 
   221 	const std::string receive() override {
   226 	const std::string receive() override {
   222 		// TODO: SCTP receive()
   227 		// TODO: SCTP receive()
       
   228 		return "TODO: receive() a message";
       
   229 	}
       
   230 };
       
   231 
       
   232 class UDSClientSocket : public Socket {
       
   233 private:
       
   234 	FD socket;
       
   235 
       
   236 public:
       
   237 
       
   238 	UDSClientSocket(int fd) : socket(fd) {
       
   239 	}
       
   240 
       
   241 	static std::shared_ptr<Socket> open(const SocketOptions& options) {
       
   242 		struct sockaddr_un address;
       
   243 		std::string path = findOption(options, OPTION_PATH);
       
   244 
       
   245 		memset(&address, 0x00, sizeof (address));
       
   246 		address.sun_family = AF_UNIX;
       
   247 		strncpy(address.sun_path, path.c_str(), path.size());
       
   248 
       
   249 		int fd = ::socket(AF_UNIX, SOCK_STREAM, 0);
       
   250 
       
   251 		auto socket = std::make_shared<UDSClientSocket>(fd);
       
   252 		check(::connect(socket->socket.getFD(), (const sockaddr*) &address, sizeof (address)), "connect socket");
       
   253 
       
   254 
       
   255 		// zjistíme UID, GID a PID klienta, který se připojil na náš unixový soket:
       
   256 		struct ucred cr;
       
   257 		socklen_t crLen = sizeof (cr);
       
   258 		memset(&cr, 0x00, crLen);
       
   259 		getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &crLen);
       
   260 
       
   261 		// při opakovaném volání vrací stále totéž:
       
   262 		// memset(&cr, 0x00, sizeof (cr));
       
   263 		// getsockopt(spojeni, SOL_SOCKET, SO_PEERCRED, &cr, &crLen);
       
   264 
       
   265 		printf("Přijato spojení\n");
       
   266 		printf("  FD = %d\n", fd);
       
   267 		printf("  klientská cesta = %s\n", address.sun_path); // tohle je vždy prázdné
       
   268 		printf("  klientský PID = %d\n", cr.pid);
       
   269 		printf("  klientský UID = %d\n", cr.uid);
       
   270 		printf("  klientský GID = %d\n", cr.gid);
       
   271 
       
   272 
       
   273 		return socket;
       
   274 	}
       
   275 
       
   276 	void send(const std::string& message) override {
       
   277 		sendmsg(socket.getFD(), message);
       
   278 	}
       
   279 
       
   280 	const std::string receive() override {
       
   281 		// TODO: UDS receive()
   223 		return "TODO: receive() a message";
   282 		return "TODO: receive() a message";
   224 	}
   283 	}
   225 };
   284 };
   226 
   285 
   227 template<const char* protocol, const char* role, const char* mode, typename SocketClass>
   286 template<const char* protocol, const char* role, const char* mode, typename SocketClass>
   247 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   306 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   248 			std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_STREAM, SCTPClientSocket >> (),
   307 			std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_STREAM, SCTPClientSocket >> (),
   249 			std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_DATAGRAM, SCTPClientSocket >> (),
   308 			std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_DATAGRAM, SCTPClientSocket >> (),
   250 			std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: do we need a stream-mode SCTP?
   309 			std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: do we need a stream-mode SCTP?
   251 			std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   310 			std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   252 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
   311 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_STREAM, UDSClientSocket >> (), // TODO: correct class
   253 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   312 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_DATAGRAM, UDSClientSocket >> (), // TODO: correct class
   254 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
   313 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_STREAM, UDSClientSocket >> (), // TODO: correct class
   255 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   314 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_DATAGRAM, UDSClientSocket >> (), // TODO: correct class
   256 };
   315 };
   257 
   316 
   258 std::shared_ptr<SocketFactory> SocketFactory::find(const SocketOptions& options) {
   317 std::shared_ptr<SocketFactory> SocketFactory::find(const SocketOptions& options) {
   259 	for (auto f : factories) if (f->canHandle(options)) return f;
   318 	for (auto f : factories) if (f->canHandle(options)) return f;
   260 	throw std::logic_error("Unable to find a SocketFactory"); // TODO: add relevant options?
   319 	throw std::logic_error("Unable to find a SocketFactory"); // TODO: add relevant options?