/network/localsocket.cpp
C++ | 302 lines | 158 code | 37 blank | 107 comment | 20 complexity | 6b486f9b55a95a2a2b6b076fad27bd0a MD5 | raw file
Possible License(s): GPL-3.0
- /****************************************************************************
- ** localsocket.cpp
- **
- ** Copyright information
- **
- ** Copyright (C) 2013-2014 Arttu Liimola <arttu.liimola@gmail.com>
- **
- ** License
- **
- ** This file is part of IrGGu-Server.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>
- **
- ****************************************************************************/
- #include "localsocket.h"
- #include "protocol/irggu.h"
- #include <sys/socket.h>
- #include <sys/un.h>
- #include <QStringListIterator>
- #include <QRegularExpression>
- #ifdef LOCAL_PEERCRED // FreeBSD, kFreeBSD, DragonFlyBSD
- #include <sys/ucred.h>
- #endif
- #if !defined(SO_PEERCRED) && !defined(LOCAL_PEERCRED) && !defined(LOCAL_PEEREID) // OpenIndiana
- #include <ucred.h>
- #endif
- /**
- * Constructor.
- *
- * @param *parent Pointer to parent.
- */
- LocalSocket::LocalSocket (QObject *parent) : QObject(parent)
- {
- socket = new QLocalSocket(this);
- uid = 0;
- uidOk = false;
- versionOk = false;
- receivedHandshake = false;
- sentHandshake = false;
- connect(socket, SIGNAL(disconnected()), this, SIGNAL(disconnected()));
- connect(socket, SIGNAL(readyRead()), this, SLOT(readData()));
- connect(socket, SIGNAL(bytesWritten(qint64)), this, SLOT(wroteBytes()));
- }
- /**
- * Disconnect socket from client.
- */
- void LocalSocket::disconnectFromClient ()
- {
- socket->disconnectFromServer();
- }
- /**
- * Get user ID.
- *
- * @return User ID.
- */
- int LocalSocket::getUid ()
- {
- return uid;
- }
- /**
- * Return true if user ID ok.
- *
- * @return True if user ID ok.
- */
- bool LocalSocket::isUidOk ()
- {
- return uidOk;
- }
- /**
- * Set socket descriptor.
- *
- * @param socketDescriptor Socket descriptor.
- * @return True if socket descriptor is accepted.
- */
- bool LocalSocket::setSocketDescriptor (qintptr socketDescriptor)
- {
- bool accepted = socket->setSocketDescriptor(socketDescriptor);
- setUid();
- return accepted;
- }
- /**
- * Return true if socket has a line to read.
- *
- * @return True if socket has a line to read.
- */
- bool LocalSocket::canReadLine ()
- {
- return socket->canReadLine();
- }
- /**
- * Read line from socket.
- *
- * @return Line from socket.
- */
- QByteArray LocalSocket::readLine ()
- {
- return socket->readLine();
- }
- /**
- * Write data to client.
- *
- * @param data Data to be written.
- * @return Number of bytes that were written.
- */
- qint64 LocalSocket::write (const char *data)
- {
- return socket->write(data);
- }
- /**
- * Return amount of bytes that has not been written.
- *
- * @return Amount of bytes that has not been written.
- */
- qint64 LocalSocket::bytesToWrite ()
- {
- return socket->bytesToWrite();
- }
- /**
- * Set user ID.
- */
- void LocalSocket::setUid ()
- {
- int sDesc = socket->socketDescriptor();
- #ifdef SO_PEERCRED // Linux, OpenBSD
- #ifdef __OpenBSD__
- sockpeercred cred;
- #else
- ucred cred;
- #endif
- socklen_t len = sizeof(cred);
- if( getsockopt(sDesc, SOL_SOCKET, SO_PEERCRED, &cred, &len) == 0 )
- {
- uid = cred.uid;
- uidOk = true;
- }
- #elif defined(LOCAL_PEERCRED) // FreeBSD, kFreeBSD, DragonFlyBSD
- xucred cred;
- socklen_t len = sizeof(cred);
- if( getsockopt(sDesc, 0, LOCAL_PEERCRED, &cred, &len) == 0 )
- {
- uid = cred.cr_uid;
- uidOk = true;
- }
- #elif defined(LOCAL_PEEREID) // NetBSD
- unpcbid cred;
- socklen_t len = sizeof(cred);
- if ( getsockopt(sDesc, 0, LOCAL_PEEREID, &cred, &len) == 0 )
- {
- uid = cred.unp_euid;
- uidOk = true;
- }
- #else // OpenIndiana
- ucred_t * ucred = NULL;
- if ( getpeerucred(sDesc, &ucred) == 0 )
- {
- uid = ucred_geteuid(ucred);
- uidOk = true;
- }
- #endif
- }
- /**
- * Handle handshake.
- *
- * @param line Handshake.
- */
- void LocalSocket::handleHandshake (QString line)
- {
- QRegularExpression re(IrGGu_IRC_Handshake::receive);
- QRegularExpressionMatch rem = re.match(line);
- if ( rem.hasMatch() )
- {
- receivedHandshake = true;
- versionOk = rem.captured("version").toFloat() == IrGGu_IRC::version;
- writeServerHandshake();
- }
- else
- {
- socket->disconnectFromServer();
- }
- }
- /**
- * Write handshake.
- */
- void LocalSocket::writeServerHandshake ()
- {
- if ( receivedHandshake )
- {
- QString version = QString::number(IrGGu_IRC::version, 10, 1);
- QString line = IrGGu_IRC_Handshake::write + "\n";
- line.replace("<version>", version);
- write(line.toUtf8());
- }
- }
- /**
- * Read data sent by client.
- */
- void LocalSocket::readData ()
- {
- if ( !sentHandshake )
- {
- QString line;
- while ( socket->canReadLine() )
- {
- line = QString::fromUtf8(socket->readLine()).trimmed();
- handleHandshake(line);
- }
- }
- else
- {
- Q_EMIT readyRead();
- }
- }
- /**
- * Called when data has been sent to client.
- */
- void LocalSocket::wroteBytes ()
- {
- if ( !sentHandshake )
- {
- if ( versionOk )
- {
- sentHandshake = true;
- Q_EMIT connected();
- }
- else if ( socket->bytesToWrite() == 0 )
- {
- socket->disconnectFromServer();
- }
- }
- else
- {
- Q_EMIT bytesWritten();
- }
- }
- /**
- * Signal is emitted when socket is in connected state.
- *
- * @fn void LocalSocket::connected()
- */
- /**
- * Signal is emitted when socket is in disconnected state.
- *
- * @fn void LocalSocket::disconnected()
- */
- /**
- * Signal is emitted when socket has data for reading.
- *
- * @fn void LocalSocket::readyRead()
- */
- /**
- * Signal is emitted when socket wrote data.
- *
- * @fn void LocalSocket::bytesWritten()
- */