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 } |