src/Socket.cpp
branchv_0
changeset 9 de48b9278211
parent 7 e6f005f3edfe
child 10 6a6b93507856
equal deleted inserted replaced
8:3e17086fffea 9:de48b9278211
    55 	int getFD() {
    55 	int getFD() {
    56 		return fd;
    56 		return fd;
    57 	}
    57 	}
    58 };
    58 };
    59 
    59 
    60 class UDPSocket : public Socket {
    60 static void check(int result, std::string message) {
       
    61 	if (result == 0); // OK
       
    62 	else throw std::logic_error("Got error result: " + std::to_string(result) + " - " + message);
       
    63 }
       
    64 
       
    65 class UDPClientSocket : public Socket {
       
    66 private:
       
    67 	struct sockaddr_in remoteAddress;
       
    68 	int protocol = IPPROTO_UDP;
       
    69 	int type = SOCK_DGRAM;
       
    70 public:
       
    71 
       
    72 	static std::shared_ptr<Socket> open(const SocketOptions& options) {
       
    73 		std::shared_ptr<UDPClientSocket> s = std::make_shared<UDPClientSocket>();
       
    74 		memset((char *) &s->remoteAddress, 0, sizeof (s->remoteAddress));
       
    75 		s->remoteAddress.sin_family = AF_INET;
       
    76 		s->remoteAddress.sin_addr.s_addr = inet_addr(findOption(options, OPTION_HOST, true).c_str()); // TODO: use getaddrinfo() instead (because of error -1 = 255.255.255.255)
       
    77 		s->remoteAddress.sin_port = htons(std::stoi(findOption(options, OPTION_PORT, true)));
       
    78 
       
    79 		auto protocol = findOption(options, OPTION_PROTOCOL);
       
    80 		if (protocol == PROTOCOL_SCTP) {
       
    81 			s->protocol = IPPROTO_SCTP;
       
    82 			s->type = SOCK_SEQPACKET;
       
    83 		}
       
    84 
       
    85 		return s;
       
    86 	}
       
    87 
       
    88 	void send(const std::string& message) override {
       
    89 		FD s(::socket(AF_INET, type, protocol));
       
    90 		sendto(s.getFD(), message.c_str(), message.size(), 0, (sockaddr*) & remoteAddress, sizeof (remoteAddress));
       
    91 	}
       
    92 
       
    93 	const std::string receive() override {
       
    94 		// TODO: TCP receive()
       
    95 		return "TODO: receive() a message";
       
    96 	}
       
    97 
       
    98 };
       
    99 
       
   100 class TCPClientSocket : public Socket {
    61 private:
   101 private:
    62 	struct sockaddr_in remoteAddress;
   102 	struct sockaddr_in remoteAddress;
    63 public:
   103 public:
    64 
   104 
    65 	static std::shared_ptr<Socket> open(const SocketOptions& options) {
   105 	static std::shared_ptr<Socket> open(const SocketOptions& options) {
    66 		std::shared_ptr<UDPSocket> s = std::make_shared<UDPSocket>();
   106 		std::shared_ptr<TCPClientSocket> s = std::make_shared<TCPClientSocket>();
    67 		memset((char *) &s->remoteAddress, 0, sizeof (s->remoteAddress));
   107 		memset((char *) &s->remoteAddress, 0, sizeof (s->remoteAddress));
    68 		s->remoteAddress.sin_family = AF_INET;
   108 		s->remoteAddress.sin_family = AF_INET;
    69 		s->remoteAddress.sin_addr.s_addr = inet_addr(findOption(options, OPTION_HOST, true).c_str()); // TODO: use getaddrinfo() instead (because of error -1 = 255.255.255.255)
   109 		s->remoteAddress.sin_addr.s_addr = inet_addr(findOption(options, OPTION_HOST, true).c_str()); // TODO: use getaddrinfo() instead (because of error -1 = 255.255.255.255)
    70 		s->remoteAddress.sin_port = htons(std::stoi(findOption(options, OPTION_PORT, true)));
   110 		s->remoteAddress.sin_port = htons(std::stoi(findOption(options, OPTION_PORT, true)));
    71 		return s;
   111 		return s;
    72 	}
   112 	}
    73 
   113 
    74 	void send(const std::string& message) override {
   114 	void send(const std::string& message) override {
    75 		FD s(::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
   115 		FD s(::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
    76 		sendto(s.getFD(), message.c_str(), message.size(), 0, (sockaddr*) & remoteAddress, sizeof (remoteAddress));
   116 		check(::connect(s.getFD(), (sockaddr*) & remoteAddress, sizeof (remoteAddress)), "connect socket");
       
   117 		ssize_t written = ::write(s.getFD(), message.c_str(), message.size());
       
   118 		if (written != message.size()) throw std::logic_error("writing to the socket failed");
    77 	}
   119 	}
    78 
   120 
    79 	const std::string receive() override {
   121 	const std::string receive() override {
    80 		// TODO: TCP receive()
   122 		// TODO: TCP receive()
    81 		return "TODO: receive() a message";
   123 		return "TODO: receive() a message";
    82 	}
   124 	}
       
   125 
    83 
   126 
    84 };
   127 };
    85 
   128 
    86 template<const char* protocol, const char* role, const char* mode, typename SocketClass>
   129 template<const char* protocol, const char* role, const char* mode, typename SocketClass>
    87 class TemplateSocketFactory : public SocketFactory {
   130 class TemplateSocketFactory : public SocketFactory {
    98 	}
   141 	}
    99 };
   142 };
   100 
   143 
   101 static std::vector<std::shared_ptr<SocketFactory>> factories
   144 static std::vector<std::shared_ptr<SocketFactory>> factories
   102 {
   145 {
   103 	// FIXME: different classes than UDPSocket
   146 	std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_CLIENT, MODE_STREAM, TCPClientSocket >> (),
   104 	std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_CLIENT, MODE_STREAM, UDPSocket >> (),
   147 	std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_SERVER, MODE_STREAM, TCPClientSocket >> (), // TODO: correct class
   105 	std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_SERVER, MODE_STREAM, UDPSocket >> (),
   148 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (),
   106 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_CLIENT, MODE_DATAGRAM, UDPSocket >> (),
   149 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   107 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_SERVER, MODE_DATAGRAM, UDPSocket >> (),
   150 	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
   108 	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_STREAM, UDPSocket >> (),
   151 	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   109 	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_DATAGRAM, UDPSocket >> (),
   152 	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
   110 	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_STREAM, UDPSocket >> (),
   153 	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   111 	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_DATAGRAM, UDPSocket >> (),
   154 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
   112 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_STREAM, UDPSocket >> (),
   155 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   113 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_DATAGRAM, UDPSocket >> (),
   156 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
   114 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_STREAM, UDPSocket >> (),
   157 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   115 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_DATAGRAM, UDPSocket >> (),
       
   116 };
   158 };
   117 
   159 
   118 std::shared_ptr<SocketFactory> SocketFactory::find(const SocketOptions& options) {
   160 std::shared_ptr<SocketFactory> SocketFactory::find(const SocketOptions& options) {
   119 	for (auto f : factories) if (f->canHandle(options)) return f;
   161 	for (auto f : factories) if (f->canHandle(options)) return f;
   120 	throw std::logic_error("Unable to find a SocketFactory"); // TODO: add relevant options?
   162 	throw std::logic_error("Unable to find a SocketFactory"); // TODO: add relevant options?