1 | /* |
2 | SPDX-FileCopyrightText: 2017 Chinmoy Ranjan Pradhan <chinmoyrp65@gmail.com> |
3 | |
4 | SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL |
5 | */ |
6 | |
7 | #include "fdreceiver.h" |
8 | |
9 | #include <QSocketNotifier> |
10 | #include <cerrno> |
11 | |
12 | #include "sharefd_p.h" |
13 | |
14 | FdReceiver::FdReceiver(const std::string &path, QObject *parent) |
15 | : QObject(parent) |
16 | , m_readNotifier(nullptr) |
17 | , m_path(path) |
18 | , m_socketDes(-1) |
19 | , m_fileDes(-1) |
20 | { |
21 | const SocketAddress addr(m_path); |
22 | if (!addr.address()) { |
23 | std::cerr << "Invalid socket address:" << m_path << std::endl; |
24 | return; |
25 | } |
26 | |
27 | m_socketDes = ::socket(AF_LOCAL, SOCK_STREAM | SOCK_NONBLOCK, protocol: 0); |
28 | if (m_socketDes == -1) { |
29 | std::cerr << "socket error:" << strerror(errno) << std::endl; |
30 | return; |
31 | } |
32 | |
33 | ::unlink(name: m_path.c_str()); |
34 | if (bind(fd: m_socketDes, addr: addr.address(), len: addr.length()) != 0 || listen(fd: m_socketDes, n: 5) != 0) { |
35 | std::cerr << "bind/listen error:" << strerror(errno) << std::endl; |
36 | ::close(fd: m_socketDes); |
37 | m_socketDes = -1; |
38 | return; |
39 | } |
40 | |
41 | m_readNotifier = new QSocketNotifier(m_socketDes, QSocketNotifier::Read, this); |
42 | connect(sender: m_readNotifier, signal: &QSocketNotifier::activated, context: this, slot: &FdReceiver::receiveFileDescriptor); |
43 | } |
44 | |
45 | FdReceiver::~FdReceiver() |
46 | { |
47 | if (m_socketDes >= 0) { |
48 | ::close(fd: m_socketDes); |
49 | } |
50 | ::unlink(name: m_path.c_str()); |
51 | } |
52 | |
53 | bool FdReceiver::isListening() const |
54 | { |
55 | return m_socketDes >= 0 && m_readNotifier; |
56 | } |
57 | |
58 | void FdReceiver::receiveFileDescriptor() |
59 | { |
60 | int client = ::accept(fd: m_socketDes, addr: nullptr, addr_len: nullptr); |
61 | if (client > 0) { |
62 | FDMessageHeader msg; |
63 | if (::recvmsg(fd: client, message: msg.message(), flags: 0) == 2) { |
64 | ::memcpy(dest: &m_fileDes, CMSG_DATA(msg.cmsgHeader()), n: sizeof m_fileDes); |
65 | } |
66 | ::close(fd: client); |
67 | } |
68 | } |
69 | |
70 | int FdReceiver::fileDescriptor() const |
71 | { |
72 | return m_fileDes; |
73 | } |
74 | |
75 | #include "moc_fdreceiver.cpp" |
76 | |