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