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 |