src/Socket.cpp
branchv_0
changeset 10 6a6b93507856
parent 9 de48b9278211
child 11 a910051cd975
equal deleted inserted replaced
9:de48b9278211 10:6a6b93507856
    23 #include <sys/socket.h>
    23 #include <sys/socket.h>
    24 #include <netinet/in.h>
    24 #include <netinet/in.h>
    25 #include <vector>
    25 #include <vector>
    26 #include <memory>
    26 #include <memory>
    27 #include <regex>
    27 #include <regex>
       
    28 #include <iostream>
       
    29 #include <netdb.h>
    28 
    30 
    29 #include "Socket.h"
    31 #include "Socket.h"
    30 
    32 
    31 namespace relpipe {
    33 namespace relpipe {
    32 namespace out {
    34 namespace out {
    58 };
    60 };
    59 
    61 
    60 static void check(int result, std::string message) {
    62 static void check(int result, std::string message) {
    61 	if (result == 0); // OK
    63 	if (result == 0); // OK
    62 	else throw std::logic_error("Got error result: " + std::to_string(result) + " - " + message);
    64 	else throw std::logic_error("Got error result: " + std::to_string(result) + " - " + message);
       
    65 }
       
    66 
       
    67 template <typename T> static T* castAddress(addrinfo* ai, sa_family_t family) {
       
    68 	if (ai && ai->ai_family == family && sizeof (T) == ai->ai_addrlen) return (T*) ai->ai_addr;
       
    69 	else return nullptr;
       
    70 }
       
    71 
       
    72 static std::string ip2string(const addrinfo* ai) {
       
    73 	//char buffer[INET_ADDRSTRLEN] = {0};
       
    74 	char buffer[INET6_ADDRSTRLEN] = {0};
       
    75 	//return inet_ntop(ai->ai_family, &ai->ai_addr, buffer, sizeof (buffer));
       
    76 	//return inet_ntop(ai->ai_family, &ai->ai_addr->sa_data, buffer, sizeof (buffer));
       
    77 	if (ai->ai_family == AF_INET) return inet_ntop(ai->ai_family, &((sockaddr_in const *) ai->ai_addr)->sin_addr, buffer, sizeof (buffer)); // TODO: check 0 result
       
    78 	else if (ai->ai_family == AF_INET6) return inet_ntop(ai->ai_family, &((sockaddr_in6 const *) ai->ai_addr)->sin6_addr, buffer, sizeof (buffer)); // TODO: check 0 result
       
    79 	else throw std::logic_error("Invalid address family: " + std::to_string(ai->ai_family));
       
    80 }
       
    81 
       
    82 static in_addr_t getAddress(const std::string& host) {
       
    83 
       
    84 	struct addrinfo* addrInfo;
       
    85 	check(getaddrinfo(host.c_str(), "", nullptr, &addrInfo), "getaddrinfo");
       
    86 
       
    87 	std::cerr << "found: " << addrInfo << std::endl;
       
    88 	if (addrInfo) {
       
    89 		for (addrinfo* ai = addrInfo; ai; ai = ai->ai_next) {
       
    90 			std::cerr << "address info: family=" << std::to_string(ai->ai_addr->sa_family);
       
    91 			if (sockaddr_in * sa = castAddress<sockaddr_in>(ai, AF_INET)) std::cerr << " IPv4=" << ip2string(ai);
       
    92 			else if (sockaddr_in6 * sa = castAddress<sockaddr_in6>(ai, AF_INET6)) std::cerr << " IPv6=" << ip2string(ai);
       
    93 			std::cerr << std::endl;
       
    94 		}
       
    95 	}
       
    96 
       
    97 	if (addrInfo) {
       
    98 		for (addrinfo* ai = addrInfo; ai; ai = ai->ai_next) {
       
    99 			if (sockaddr_in * sa = castAddress<sockaddr_in>(ai, AF_INET)) {
       
   100 				in_addr_t address = sa->sin_addr.s_addr;
       
   101 				freeaddrinfo(addrInfo);
       
   102 				return address;
       
   103 
       
   104 			}
       
   105 		}
       
   106 	}
       
   107 
       
   108 	freeaddrinfo(addrInfo);
       
   109 
       
   110 	// TODO: rather throw exception – requires IP address in the host string:
       
   111 	return inet_addr(host.c_str());
    63 }
   112 }
    64 
   113 
    65 class UDPClientSocket : public Socket {
   114 class UDPClientSocket : public Socket {
    66 private:
   115 private:
    67 	struct sockaddr_in remoteAddress;
   116 	struct sockaddr_in remoteAddress;
    71 
   120 
    72 	static std::shared_ptr<Socket> open(const SocketOptions& options) {
   121 	static std::shared_ptr<Socket> open(const SocketOptions& options) {
    73 		std::shared_ptr<UDPClientSocket> s = std::make_shared<UDPClientSocket>();
   122 		std::shared_ptr<UDPClientSocket> s = std::make_shared<UDPClientSocket>();
    74 		memset((char *) &s->remoteAddress, 0, sizeof (s->remoteAddress));
   123 		memset((char *) &s->remoteAddress, 0, sizeof (s->remoteAddress));
    75 		s->remoteAddress.sin_family = AF_INET;
   124 		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)
   125 		s->remoteAddress.sin_addr.s_addr = getAddress(findOption(options, OPTION_HOST, true)); // 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)));
   126 		s->remoteAddress.sin_port = htons(std::stoi(findOption(options, OPTION_PORT, true)));
    78 
   127 
    79 		auto protocol = findOption(options, OPTION_PROTOCOL);
   128 		auto protocol = findOption(options, OPTION_PROTOCOL);
    80 		if (protocol == PROTOCOL_SCTP) {
   129 		if (protocol == PROTOCOL_SCTP) {
    81 			s->protocol = IPPROTO_SCTP;
   130 			s->protocol = IPPROTO_SCTP;
   104 
   153 
   105 	static std::shared_ptr<Socket> open(const SocketOptions& options) {
   154 	static std::shared_ptr<Socket> open(const SocketOptions& options) {
   106 		std::shared_ptr<TCPClientSocket> s = std::make_shared<TCPClientSocket>();
   155 		std::shared_ptr<TCPClientSocket> s = std::make_shared<TCPClientSocket>();
   107 		memset((char *) &s->remoteAddress, 0, sizeof (s->remoteAddress));
   156 		memset((char *) &s->remoteAddress, 0, sizeof (s->remoteAddress));
   108 		s->remoteAddress.sin_family = AF_INET;
   157 		s->remoteAddress.sin_family = AF_INET;
   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)
   158 		s->remoteAddress.sin_addr.s_addr = getAddress(findOption(options, OPTION_HOST, true).c_str()); // TODO: use getaddrinfo() instead (because of error -1 = 255.255.255.255)
   110 		s->remoteAddress.sin_port = htons(std::stoi(findOption(options, OPTION_PORT, true)));
   159 		s->remoteAddress.sin_port = htons(std::stoi(findOption(options, OPTION_PORT, true)));
   111 		return s;
   160 		return s;
   112 	}
   161 	}
   113 
   162 
   114 	void send(const std::string& message) override {
   163 	void send(const std::string& message) override {
   142 };
   191 };
   143 
   192 
   144 static std::vector<std::shared_ptr<SocketFactory>> factories
   193 static std::vector<std::shared_ptr<SocketFactory>> factories
   145 {
   194 {
   146 	std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_CLIENT, MODE_STREAM, TCPClientSocket >> (),
   195 	std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_CLIENT, MODE_STREAM, TCPClientSocket >> (),
   147 	std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_SERVER, MODE_STREAM, TCPClientSocket >> (), // TODO: correct class
   196 			std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_SERVER, MODE_STREAM, TCPClientSocket >> (), // TODO: correct class
   148 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (),
   197 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (),
   149 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   198 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   150 	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
   199 			std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
   151 	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   200 			std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   152 	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
   201 			std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
   153 	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   202 			std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   154 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
   203 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
   155 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   204 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   156 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
   205 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
   157 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   206 			std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
   158 };
   207 };
   159 
   208 
   160 std::shared_ptr<SocketFactory> SocketFactory::find(const SocketOptions& options) {
   209 std::shared_ptr<SocketFactory> SocketFactory::find(const SocketOptions& options) {
   161 	for (auto f : factories) if (f->canHandle(options)) return f;
   210 	for (auto f : factories) if (f->canHandle(options)) return f;
   162 	throw std::logic_error("Unable to find a SocketFactory"); // TODO: add relevant options?
   211 	throw std::logic_error("Unable to find a SocketFactory"); // TODO: add relevant options?