132 protocol); |
133 protocol); |
133 |
134 |
134 return std::shared_ptr<SocketClass>(new SocketClass(remoteAddresses[0], moreArgs...)); |
135 return std::shared_ptr<SocketClass>(new SocketClass(remoteAddresses[0], moreArgs...)); |
135 } |
136 } |
136 |
137 |
|
138 void sendmsg(int fd, const std::string& message) { |
|
139 iovec iov[1]; |
|
140 msghdr msg = {}; |
|
141 msg.msg_iov = iov; |
|
142 msg.msg_iov[0].iov_base = (void*) message.c_str(); |
|
143 msg.msg_iov[0].iov_len = message.size(); |
|
144 msg.msg_iovlen = sizeof (iov) / sizeof (iov[0]); |
|
145 ssize_t written = ::sendmsg(fd, &msg, 0); |
|
146 if (written != message.size()) throw std::logic_error("writing to the socket failed"); |
|
147 } |
|
148 |
137 class UDPClientSocket : public Socket { |
149 class UDPClientSocket : public Socket { |
138 private: |
150 private: |
139 AddressInfos::AddressInfo remoteAddress; |
151 AddressInfos::AddressInfo remoteAddress; |
140 useconds_t delay = 0; |
152 useconds_t delay = 0; |
141 FD socket; |
153 FD socket; |
206 check(::connect(socket->socket.getFD(), socket->remoteAddress.ai->ai_addr, socket->remoteAddress.ai->ai_addrlen), "connect socket"); |
218 check(::connect(socket->socket.getFD(), socket->remoteAddress.ai->ai_addr, socket->remoteAddress.ai->ai_addrlen), "connect socket"); |
207 return socket; |
219 return socket; |
208 } |
220 } |
209 |
221 |
210 void send(const std::string& message) override { |
222 void send(const std::string& message) override { |
211 iovec iov[1]; |
223 sendmsg(socket.getFD(), message); |
212 msghdr msg = {}; |
|
213 msg.msg_iov = iov; |
|
214 msg.msg_iov[0].iov_base = (void*) message.c_str(); |
|
215 msg.msg_iov[0].iov_len = message.size(); |
|
216 msg.msg_iovlen = sizeof (iov) / sizeof (iov[0]); |
|
217 ssize_t written = ::sendmsg(socket.getFD(), &msg, 0); |
|
218 if (written != message.size()) throw std::logic_error("writing to the socket failed"); |
|
219 } |
224 } |
220 |
225 |
221 const std::string receive() override { |
226 const std::string receive() override { |
222 // TODO: SCTP receive() |
227 // TODO: SCTP receive() |
|
228 return "TODO: receive() a message"; |
|
229 } |
|
230 }; |
|
231 |
|
232 class UDSClientSocket : public Socket { |
|
233 private: |
|
234 FD socket; |
|
235 |
|
236 public: |
|
237 |
|
238 UDSClientSocket(int fd) : socket(fd) { |
|
239 } |
|
240 |
|
241 static std::shared_ptr<Socket> open(const SocketOptions& options) { |
|
242 struct sockaddr_un address; |
|
243 std::string path = findOption(options, OPTION_PATH); |
|
244 |
|
245 memset(&address, 0x00, sizeof (address)); |
|
246 address.sun_family = AF_UNIX; |
|
247 strncpy(address.sun_path, path.c_str(), path.size()); |
|
248 |
|
249 int fd = ::socket(AF_UNIX, SOCK_STREAM, 0); |
|
250 |
|
251 auto socket = std::make_shared<UDSClientSocket>(fd); |
|
252 check(::connect(socket->socket.getFD(), (const sockaddr*) &address, sizeof (address)), "connect socket"); |
|
253 |
|
254 |
|
255 // zjistíme UID, GID a PID klienta, který se připojil na náš unixový soket: |
|
256 struct ucred cr; |
|
257 socklen_t crLen = sizeof (cr); |
|
258 memset(&cr, 0x00, crLen); |
|
259 getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &crLen); |
|
260 |
|
261 // při opakovaném volání vrací stále totéž: |
|
262 // memset(&cr, 0x00, sizeof (cr)); |
|
263 // getsockopt(spojeni, SOL_SOCKET, SO_PEERCRED, &cr, &crLen); |
|
264 |
|
265 printf("Přijato spojení\n"); |
|
266 printf(" FD = %d\n", fd); |
|
267 printf(" klientská cesta = %s\n", address.sun_path); // tohle je vždy prázdné |
|
268 printf(" klientský PID = %d\n", cr.pid); |
|
269 printf(" klientský UID = %d\n", cr.uid); |
|
270 printf(" klientský GID = %d\n", cr.gid); |
|
271 |
|
272 |
|
273 return socket; |
|
274 } |
|
275 |
|
276 void send(const std::string& message) override { |
|
277 sendmsg(socket.getFD(), message); |
|
278 } |
|
279 |
|
280 const std::string receive() override { |
|
281 // TODO: UDS receive() |
223 return "TODO: receive() a message"; |
282 return "TODO: receive() a message"; |
224 } |
283 } |
225 }; |
284 }; |
226 |
285 |
227 template<const char* protocol, const char* role, const char* mode, typename SocketClass> |
286 template<const char* protocol, const char* role, const char* mode, typename SocketClass> |
247 std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class |
306 std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class |
248 std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_STREAM, SCTPClientSocket >> (), |
307 std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_STREAM, SCTPClientSocket >> (), |
249 std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_DATAGRAM, SCTPClientSocket >> (), |
308 std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_DATAGRAM, SCTPClientSocket >> (), |
250 std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: do we need a stream-mode SCTP? |
309 std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: do we need a stream-mode SCTP? |
251 std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class |
310 std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class |
252 std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class |
311 std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_STREAM, UDSClientSocket >> (), // TODO: correct class |
253 std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class |
312 std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_DATAGRAM, UDSClientSocket >> (), // TODO: correct class |
254 std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class |
313 std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_STREAM, UDSClientSocket >> (), // TODO: correct class |
255 std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class |
314 std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_DATAGRAM, UDSClientSocket >> (), // TODO: correct class |
256 }; |
315 }; |
257 |
316 |
258 std::shared_ptr<SocketFactory> SocketFactory::find(const SocketOptions& options) { |
317 std::shared_ptr<SocketFactory> SocketFactory::find(const SocketOptions& options) { |
259 for (auto f : factories) if (f->canHandle(options)) return f; |
318 for (auto f : factories) if (f->canHandle(options)) return f; |
260 throw std::logic_error("Unable to find a SocketFactory"); // TODO: add relevant options? |
319 throw std::logic_error("Unable to find a SocketFactory"); // TODO: add relevant options? |