src/Socket.cpp
branchv_0
changeset 5 e57e2a2798b2
parent 4 8d036e5e5fcc
child 7 e6f005f3edfe
equal deleted inserted replaced
4:8d036e5e5fcc 5:e57e2a2798b2
    25 #include <vector>
    25 #include <vector>
    26 #include <memory>
    26 #include <memory>
    27 #include <regex>
    27 #include <regex>
    28 
    28 
    29 #include "Socket.h"
    29 #include "Socket.h"
       
    30 #include "Configuration.h"
    30 
    31 
    31 namespace relpipe {
    32 namespace relpipe {
    32 namespace out {
    33 namespace out {
    33 namespace socket {
    34 namespace socket {
    34 
    35 
    35 static const char PROTOCOL_TCP[] = "tcp://";
    36 using namespace relpipe::out::socket::options;
    36 static const char PROTOCOL_UDP[] = "udp://";
    37 
    37 static const char PROTOCOL_UDS[] = "uds://";
    38 static const std::string findOption(SocketOptions options, std::string name, bool required = false, const std::string defaultValue = "") {
    38 static const char PROTOCOL_SCTP[] = "sctp://";
    39 	for (auto o : options) if (o.name == name) return o.value;
    39 static const char PROTOCOL_TCP_LISTEN[] = "tcp-listen://";
    40 	if (required) throw std::invalid_argument("Option " + name + " is required but was not found");
    40 static const char PROTOCOL_UDP_LISTEN[] = "udp-listen://";
    41 	else return defaultValue;
    41 static const char PROTOCOL_UDS_LISTEN[] = "uds-listen://";
    42 }
    42 static const char PROTOCOL_SCTP_LISTEN[] = "sctp-listen://";
       
    43 
    43 
    44 class FD {
    44 class FD {
    45 private:
    45 private:
    46 	int fd;
    46 	int fd;
    47 public:
    47 public:
    56 	int getFD() {
    56 	int getFD() {
    57 		return fd;
    57 		return fd;
    58 	}
    58 	}
    59 };
    59 };
    60 
    60 
    61 /**
       
    62  * @param connectionString
       
    63  * @return protocol, hostname or path, port (optional)
       
    64  */
       
    65 static std::tuple<std::string, std::string, uint16_t> parseConnectionString(const std::string& connectionString) {
       
    66 	// TODO: support „:“ in domain socket paths?
       
    67 	std::regex pattern("([^:]+)://([^:]+)(:([0-9]+))?");
       
    68 	
       
    69 }
       
    70 
       
    71 class UDPSocket : public Socket {
    61 class UDPSocket : public Socket {
    72 private:
    62 private:
    73 	struct sockaddr_in remoteAddress;
    63 	struct sockaddr_in remoteAddress;
    74 public:
    64 public:
    75 
    65 
    76 	static std::shared_ptr<Socket> open(const std::string& connectionString) {
    66 	static std::shared_ptr<Socket> open(const SocketOptions& options) {
    77 		std::shared_ptr<UDPSocket> s = std::make_shared<UDPSocket>();
    67 		std::shared_ptr<UDPSocket> s = std::make_shared<UDPSocket>();
    78 		memset((char *) &s->remoteAddress, 0, sizeof (s->remoteAddress));
    68 		memset((char *) &s->remoteAddress, 0, sizeof (s->remoteAddress));
    79 		s->remoteAddress.sin_family = AF_INET;
    69 		s->remoteAddress.sin_family = AF_INET;
    80 		s->remoteAddress.sin_addr.s_addr = inet_addr("127.0.0.1"); // TODO: use getaddrinfo() instead (because of error -1 = 255.255.255.255)
    70 		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)
    81 		s->remoteAddress.sin_port = htons(1234);
    71 		s->remoteAddress.sin_port = htons(std::stoi(findOption(options, OPTION_PORT, true)));
    82 		return s;
    72 		return s;
    83 	}
    73 	}
    84 
    74 
    85 	void send(const std::string& message) override {
    75 	void send(const std::string& message) override {
    86 		FD s(::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
    76 		FD s(::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
    92 		return "TODO: receive() a message";
    82 		return "TODO: receive() a message";
    93 	}
    83 	}
    94 
    84 
    95 };
    85 };
    96 
    86 
    97 template<const char* protocol, typename SocketClass>
    87 template<const char* protocol, const char* role, const char* mode, typename SocketClass>
    98 class TemplateSocketFactory : public SocketFactory {
    88 class TemplateSocketFactory : public SocketFactory {
    99 public:
    89 public:
   100 
    90 
   101 	bool canHandle(const std::string& connectionString) override {
    91 	bool canHandle(const SocketOptions& options) override {
   102 		return connectionString.rfind(protocol, 0) == 0;
    92 		return findOption(options, OPTION_PROTOCOL) == protocol
       
    93 				&& findOption(options, OPTION_ROLE) == role
       
    94 				&& findOption(options, OPTION_MODE) == mode;
   103 	}
    95 	}
   104 
    96 
   105 	std::shared_ptr<Socket> open(const std::string& connectionString) override {
    97 	std::shared_ptr<Socket> open(const SocketOptions& options) override {
   106 		// TODO: pass string to constructor
    98 		return SocketClass::open(options);
   107 		// TODO: return shared_ptr?
       
   108 		return SocketClass::open(connectionString);
       
   109 	}
    99 	}
   110 };
   100 };
   111 
   101 
   112 static std::vector<std::shared_ptr<SocketFactory>> factories
   102 static std::vector<std::shared_ptr<SocketFactory>> factories
   113 {
   103 {
   114 	// FIXME: different classes than TCPSocket
   104 	// FIXME: different classes than UDPSocket
   115 	std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, UDPSocket >> (),
   105 	std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_CLIENT, MODE_STREAM, UDPSocket >> (),
   116 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, UDPSocket >> (),
   106 	std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_SERVER, MODE_STREAM, UDPSocket >> (),
   117 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, UDPSocket >> (),
   107 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_CLIENT, MODE_DATAGRAM, UDPSocket >> (),
   118 	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, UDPSocket >> (),
   108 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_SERVER, MODE_DATAGRAM, UDPSocket >> (),
       
   109 	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_STREAM, UDPSocket >> (),
       
   110 	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_DATAGRAM, UDPSocket >> (),
       
   111 	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_STREAM, UDPSocket >> (),
       
   112 	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_DATAGRAM, UDPSocket >> (),
       
   113 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_STREAM, UDPSocket >> (),
       
   114 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_DATAGRAM, UDPSocket >> (),
       
   115 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_STREAM, UDPSocket >> (),
       
   116 	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_DATAGRAM, UDPSocket >> (),
   119 };
   117 };
   120 
   118 
   121 std::shared_ptr<SocketFactory> SocketFactory::find(const std::string& connectionString) {
   119 std::shared_ptr<SocketFactory> SocketFactory::find(const SocketOptions& options) {
   122 	for (auto f : factories) if (f->canHandle(connectionString)) return f;
   120 	for (auto f : factories) if (f->canHandle(options)) return f;
   123 	throw std::logic_error("Unable to find a SocketFactory for connection string: " + connectionString);
   121 	throw std::logic_error("Unable to find a SocketFactory"); // TODO: add relevant options?
   124 }
   122 }
   125 
   123 
   126 
   124 
   127 }
   125 }
   128 }
   126 }