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