Commit ac7ba427e219a5e2cae1106fb829484bb094d7c6
0 parents
Exists in
master
Qt용 UnixDomainDatagramSocket, Logger 클래스 추가
Showing
4 changed files
with
270 additions
and
0 deletions
Show diff stats
qt/logger.cpp
... | ... | @@ -0,0 +1,45 @@ |
1 | +#include "logger.h" | |
2 | + | |
3 | +#include <QDebug> | |
4 | + | |
5 | +Logger::Logger(QObject *parent) | |
6 | + : QObject(parent), | |
7 | + socket(Q_NULLPTR) | |
8 | +{ | |
9 | + | |
10 | +} | |
11 | + | |
12 | +bool Logger::init(const QString &tag) | |
13 | +{ | |
14 | + this->tag = tag; | |
15 | + if (socket == Q_NULLPTR) | |
16 | + socket = new UnixDomainDatagramSocket(this); | |
17 | + | |
18 | + return socket->open(); | |
19 | +} | |
20 | + | |
21 | +void Logger::print(const QString &string) | |
22 | +{ | |
23 | + QByteArray bytes(string.toLocal8Bit().data()); | |
24 | + bytes.prepend(' ').prepend(tag.toLocal8Bit().data()); | |
25 | + | |
26 | + qDebug() << bytes; | |
27 | + | |
28 | + socket->writeDatagram(bytes, "/tmp/logger.uds"); | |
29 | +} | |
30 | + | |
31 | +void Logger::hexdump(const QString &message, const QByteArray &bytes) | |
32 | +{ | |
33 | + QByteArray line; | |
34 | + line += tag + " " + message + " ["; | |
35 | + for (int i = 0; i < bytes.length(); i++) | |
36 | + { | |
37 | + line += QByteArray::number(uchar(bytes.at(i)), 16).toUpper(); | |
38 | + line += " "; | |
39 | + } | |
40 | + line = line.trimmed(); | |
41 | + line += "]\n"; | |
42 | + | |
43 | + qDebug() << line; | |
44 | + socket->writeDatagram(line, "/tmp/logger.uds"); | |
45 | +} | ... | ... |
qt/logger.h
... | ... | @@ -0,0 +1,29 @@ |
1 | +// Logger는 pool sw의 app-logger를 사용할 수 있게 해준다. | |
2 | + | |
3 | +#ifndef LOGGER_H | |
4 | +#define LOGGER_H | |
5 | + | |
6 | +#include <QObject> | |
7 | + | |
8 | +#include "unixdomaindatagramsocket.h" | |
9 | + | |
10 | +class Logger : public QObject | |
11 | +{ | |
12 | + Q_OBJECT | |
13 | +public: | |
14 | + explicit Logger(QObject *parent = nullptr); | |
15 | + | |
16 | + bool init(const QString &tag); | |
17 | + | |
18 | +signals: | |
19 | + | |
20 | +public slots: | |
21 | + void print(const QString &string); | |
22 | + void hexdump(const QString &message, const QByteArray &bytes); | |
23 | + | |
24 | +private: | |
25 | + UnixDomainDatagramSocket *socket; | |
26 | + QString tag; | |
27 | +}; | |
28 | + | |
29 | +#endif // LOGGER_H | ... | ... |
qt/unixdomaindatagramsocket.cpp
... | ... | @@ -0,0 +1,152 @@ |
1 | +#include "unixdomaindatagramsocket.h" | |
2 | + | |
3 | +#include <QVarLengthArray> | |
4 | + | |
5 | +#include <unistd.h> | |
6 | +#include <sys/socket.h> | |
7 | +#include <sys/un.h> | |
8 | +#include <sys/ioctl.h> | |
9 | +#include <linux/sockios.h> | |
10 | + | |
11 | +UnixDomainDatagramSocket::UnixDomainDatagramSocket(QObject *parent) | |
12 | + : QObject(parent), | |
13 | + sockfd(-1), notifier(Q_NULLPTR) | |
14 | +{ | |
15 | + | |
16 | +} | |
17 | + | |
18 | +UnixDomainDatagramSocket::~UnixDomainDatagramSocket() | |
19 | +{ | |
20 | + if (sockfd >= 0) | |
21 | + close(sockfd); | |
22 | + | |
23 | + if (!boundPath.isEmpty()) | |
24 | + unlink(boundPath.toLocal8Bit().data()); | |
25 | +} | |
26 | + | |
27 | +bool UnixDomainDatagramSocket::open() | |
28 | +{ | |
29 | + if (sockfd >= 0) | |
30 | + return false; | |
31 | + | |
32 | + sockfd = socket(AF_UNIX, SOCK_DGRAM, 0); | |
33 | + if (sockfd < 0) | |
34 | + return false; | |
35 | + | |
36 | + notifier = new QSocketNotifier(sockfd, QSocketNotifier::Read, this); | |
37 | + connect(notifier, SIGNAL(activated(int)), SLOT(emitReadyRead())); | |
38 | + | |
39 | + return true; | |
40 | +} | |
41 | + | |
42 | +bool UnixDomainDatagramSocket::bind(const QString &path) | |
43 | +{ | |
44 | + return bind(path.toLocal8Bit().data()); | |
45 | +} | |
46 | + | |
47 | +bool UnixDomainDatagramSocket::bind(const char *path) | |
48 | +{ | |
49 | + if (sockfd < 0 && !open()) | |
50 | + return false; | |
51 | + | |
52 | + unlink(path); | |
53 | + | |
54 | + struct sockaddr_un address; | |
55 | + address.sun_family = AF_UNIX; | |
56 | + strncpy(address.sun_path, path, sizeof(address.sun_path)); | |
57 | + | |
58 | + int ret = ::bind(sockfd, reinterpret_cast<struct sockaddr *>(&address), sizeof(address)); | |
59 | + if (ret == -1) | |
60 | + return false; | |
61 | + | |
62 | + return true; | |
63 | +} | |
64 | + | |
65 | +bool UnixDomainDatagramSocket::hasPendingDatagrams() | |
66 | +{ | |
67 | + ssize_t readBytes; | |
68 | + do | |
69 | + { | |
70 | + char c; | |
71 | + readBytes = ::recv(sockfd, &c, 1, MSG_DONTWAIT | MSG_PEEK); | |
72 | + } | |
73 | + while (readBytes == -1 && errno == EINTR); | |
74 | + | |
75 | + return (readBytes != -1) || errno == EMSGSIZE; | |
76 | +} | |
77 | + | |
78 | +qint64 UnixDomainDatagramSocket::pendingDatagramSize() | |
79 | +{ | |
80 | + QVarLengthArray<char, 8192> udpMessagePeekBuffer(8192); | |
81 | + ssize_t recvResult = -1; | |
82 | + | |
83 | + for (;;) | |
84 | + { | |
85 | + recvResult = ::recv(sockfd, udpMessagePeekBuffer.data(), | |
86 | + size_t(udpMessagePeekBuffer.size()), MSG_DONTWAIT | MSG_PEEK); | |
87 | + if (recvResult == -1 && errno == EINTR) | |
88 | + continue; | |
89 | + | |
90 | + if (recvResult != ssize_t(udpMessagePeekBuffer.size())) | |
91 | + break; | |
92 | + | |
93 | + udpMessagePeekBuffer.resize(udpMessagePeekBuffer.size() * 2); | |
94 | + } | |
95 | + | |
96 | + return qint64(recvResult); | |
97 | +} | |
98 | + | |
99 | +qint64 UnixDomainDatagramSocket::readDatagram(QByteArray *datagram, QString *path) | |
100 | +{ | |
101 | + return readDatagram(datagram->data(), datagram->size(), path); | |
102 | +} | |
103 | + | |
104 | +qint64 UnixDomainDatagramSocket::readDatagram(char *data, qint64 maxSize, QString *path) | |
105 | +{ | |
106 | + if (!notifier->isEnabled()) | |
107 | + notifier->setEnabled(true); | |
108 | + | |
109 | + struct sockaddr_un address; | |
110 | + socklen_t length; | |
111 | + | |
112 | + ssize_t recvResult; | |
113 | + do | |
114 | + { | |
115 | + recvResult = ::recvfrom(sockfd, data, size_t(maxSize), 0, reinterpret_cast<struct sockaddr *>(&address), &length); | |
116 | + } | |
117 | + while (recvResult == -1 && errno == EINTR); | |
118 | + | |
119 | + if (recvResult == -1) | |
120 | + return -1; | |
121 | + | |
122 | + if (path) | |
123 | + *path = QString::fromLocal8Bit(address.sun_path); | |
124 | + | |
125 | + return recvResult; | |
126 | +} | |
127 | + | |
128 | +qint64 UnixDomainDatagramSocket::writeDatagram(const QByteArray &datagram, const QString &path) | |
129 | +{ | |
130 | + return writeDatagram(datagram.data(), datagram.size(), path); | |
131 | +} | |
132 | + | |
133 | +qint64 UnixDomainDatagramSocket::writeDatagram(const char *data, qint64 size, const QString &path) | |
134 | +{ | |
135 | + return writeDatagram(data, size, path.toLocal8Bit().data()); | |
136 | +} | |
137 | + | |
138 | +qint64 UnixDomainDatagramSocket::writeDatagram(const char *data, qint64 size, const char *path) | |
139 | +{ | |
140 | + struct sockaddr_un address; | |
141 | + address.sun_family = AF_UNIX; | |
142 | + strncpy(address.sun_path, path, sizeof(address.sun_path)); | |
143 | + | |
144 | + ssize_t sendResult = ::sendto(sockfd, data, size_t(size), 0, reinterpret_cast<struct sockaddr *>(&address), sizeof(address)); | |
145 | + return qint64(sendResult); | |
146 | +} | |
147 | + | |
148 | +void UnixDomainDatagramSocket::emitReadyRead() | |
149 | +{ | |
150 | + notifier->setEnabled(false); | |
151 | + emit readyRead(); | |
152 | +} | ... | ... |
qt/unixdomaindatagramsocket.h
... | ... | @@ -0,0 +1,44 @@ |
1 | +// UnixDomainDatagramSocket은 UDS를 데이터그램 형식으로 사용하는 소켓 구현체다. QUdpSocket처럼 사용하도록 구현했다. | |
2 | +// | |
3 | +// 주의: 자동 변수 대신 new로 할당하라. 소멸자에서 열린 소켓을 닫고 만든 파일을 지우기 때문에 문제가 생길 수 있다. | |
4 | + | |
5 | +#ifndef UNIXDOMAINDATAGRAMSOCKET_H | |
6 | +#define UNIXDOMAINDATAGRAMSOCKET_H | |
7 | + | |
8 | +#include <QObject> | |
9 | +#include <QSocketNotifier> | |
10 | + | |
11 | +class UnixDomainDatagramSocket : public QObject | |
12 | +{ | |
13 | + Q_OBJECT | |
14 | +public: | |
15 | + explicit UnixDomainDatagramSocket(QObject *parent = Q_NULLPTR); | |
16 | + ~UnixDomainDatagramSocket(); | |
17 | + | |
18 | + bool open(); | |
19 | + bool bind(const QString &path); | |
20 | + bool bind(const char *path); | |
21 | + | |
22 | + bool hasPendingDatagrams(); | |
23 | + qint64 pendingDatagramSize(); | |
24 | + qint64 readDatagram(QByteArray *datagram, QString *path = Q_NULLPTR); | |
25 | + qint64 readDatagram(char *data, qint64 maxSize, QString *path = Q_NULLPTR); | |
26 | + qint64 writeDatagram(const QByteArray &datagram, const QString &path); | |
27 | + qint64 writeDatagram(const char *data, qint64 size, const QString &path); | |
28 | + qint64 writeDatagram(const char *data, qint64 size, const char *path); | |
29 | + | |
30 | +signals: | |
31 | + void readyRead(); | |
32 | + | |
33 | +public slots: | |
34 | + | |
35 | +private: | |
36 | + int sockfd; | |
37 | + QString boundPath; | |
38 | + QSocketNotifier *notifier; | |
39 | + | |
40 | +private slots: | |
41 | + void emitReadyRead(); | |
42 | +}; | |
43 | + | |
44 | +#endif // UNIXDOMAINDATAGRAMSOCKET_H | ... | ... |