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