Commit ac7ba427e219a5e2cae1106fb829484bb094d7c6

Authored by 김태훈
0 parents
Exists in master

Qt용 UnixDomainDatagramSocket, Logger 클래스 추가

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