PageRenderTime 55ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/network/localsocket.cpp

https://gitlab.com/irggu-server/irggu-server
C++ | 302 lines | 158 code | 37 blank | 107 comment | 20 complexity | 6b486f9b55a95a2a2b6b076fad27bd0a MD5 | raw file
Possible License(s): GPL-3.0
  1. /****************************************************************************
  2. ** localsocket.cpp
  3. **
  4. ** Copyright information
  5. **
  6. ** Copyright (C) 2013-2014 Arttu Liimola <arttu.liimola@gmail.com>
  7. **
  8. ** License
  9. **
  10. ** This file is part of IrGGu-Server.
  11. **
  12. ** This program is free software: you can redistribute it and/or modify
  13. ** it under the terms of the GNU General Public License as published by
  14. ** the Free Software Foundation, either version 3 of the License, or
  15. ** (at your option) any later version.
  16. **
  17. ** This program is distributed in the hope that it will be useful,
  18. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. ** GNU General Public License for more details.
  21. **
  22. ** You should have received a copy of the GNU General Public License
  23. ** along with this program. If not, see <http://www.gnu.org/licenses/>
  24. **
  25. ****************************************************************************/
  26. #include "localsocket.h"
  27. #include "protocol/irggu.h"
  28. #include <sys/socket.h>
  29. #include <sys/un.h>
  30. #include <QStringListIterator>
  31. #include <QRegularExpression>
  32. #ifdef LOCAL_PEERCRED // FreeBSD, kFreeBSD, DragonFlyBSD
  33. #include <sys/ucred.h>
  34. #endif
  35. #if !defined(SO_PEERCRED) && !defined(LOCAL_PEERCRED) && !defined(LOCAL_PEEREID) // OpenIndiana
  36. #include <ucred.h>
  37. #endif
  38. /**
  39. * Constructor.
  40. *
  41. * @param *parent Pointer to parent.
  42. */
  43. LocalSocket::LocalSocket (QObject *parent) : QObject(parent)
  44. {
  45. socket = new QLocalSocket(this);
  46. uid = 0;
  47. uidOk = false;
  48. versionOk = false;
  49. receivedHandshake = false;
  50. sentHandshake = false;
  51. connect(socket, SIGNAL(disconnected()), this, SIGNAL(disconnected()));
  52. connect(socket, SIGNAL(readyRead()), this, SLOT(readData()));
  53. connect(socket, SIGNAL(bytesWritten(qint64)), this, SLOT(wroteBytes()));
  54. }
  55. /**
  56. * Disconnect socket from client.
  57. */
  58. void LocalSocket::disconnectFromClient ()
  59. {
  60. socket->disconnectFromServer();
  61. }
  62. /**
  63. * Get user ID.
  64. *
  65. * @return User ID.
  66. */
  67. int LocalSocket::getUid ()
  68. {
  69. return uid;
  70. }
  71. /**
  72. * Return true if user ID ok.
  73. *
  74. * @return True if user ID ok.
  75. */
  76. bool LocalSocket::isUidOk ()
  77. {
  78. return uidOk;
  79. }
  80. /**
  81. * Set socket descriptor.
  82. *
  83. * @param socketDescriptor Socket descriptor.
  84. * @return True if socket descriptor is accepted.
  85. */
  86. bool LocalSocket::setSocketDescriptor (qintptr socketDescriptor)
  87. {
  88. bool accepted = socket->setSocketDescriptor(socketDescriptor);
  89. setUid();
  90. return accepted;
  91. }
  92. /**
  93. * Return true if socket has a line to read.
  94. *
  95. * @return True if socket has a line to read.
  96. */
  97. bool LocalSocket::canReadLine ()
  98. {
  99. return socket->canReadLine();
  100. }
  101. /**
  102. * Read line from socket.
  103. *
  104. * @return Line from socket.
  105. */
  106. QByteArray LocalSocket::readLine ()
  107. {
  108. return socket->readLine();
  109. }
  110. /**
  111. * Write data to client.
  112. *
  113. * @param data Data to be written.
  114. * @return Number of bytes that were written.
  115. */
  116. qint64 LocalSocket::write (const char *data)
  117. {
  118. return socket->write(data);
  119. }
  120. /**
  121. * Return amount of bytes that has not been written.
  122. *
  123. * @return Amount of bytes that has not been written.
  124. */
  125. qint64 LocalSocket::bytesToWrite ()
  126. {
  127. return socket->bytesToWrite();
  128. }
  129. /**
  130. * Set user ID.
  131. */
  132. void LocalSocket::setUid ()
  133. {
  134. int sDesc = socket->socketDescriptor();
  135. #ifdef SO_PEERCRED // Linux, OpenBSD
  136. #ifdef __OpenBSD__
  137. sockpeercred cred;
  138. #else
  139. ucred cred;
  140. #endif
  141. socklen_t len = sizeof(cred);
  142. if( getsockopt(sDesc, SOL_SOCKET, SO_PEERCRED, &cred, &len) == 0 )
  143. {
  144. uid = cred.uid;
  145. uidOk = true;
  146. }
  147. #elif defined(LOCAL_PEERCRED) // FreeBSD, kFreeBSD, DragonFlyBSD
  148. xucred cred;
  149. socklen_t len = sizeof(cred);
  150. if( getsockopt(sDesc, 0, LOCAL_PEERCRED, &cred, &len) == 0 )
  151. {
  152. uid = cred.cr_uid;
  153. uidOk = true;
  154. }
  155. #elif defined(LOCAL_PEEREID) // NetBSD
  156. unpcbid cred;
  157. socklen_t len = sizeof(cred);
  158. if ( getsockopt(sDesc, 0, LOCAL_PEEREID, &cred, &len) == 0 )
  159. {
  160. uid = cred.unp_euid;
  161. uidOk = true;
  162. }
  163. #else // OpenIndiana
  164. ucred_t * ucred = NULL;
  165. if ( getpeerucred(sDesc, &ucred) == 0 )
  166. {
  167. uid = ucred_geteuid(ucred);
  168. uidOk = true;
  169. }
  170. #endif
  171. }
  172. /**
  173. * Handle handshake.
  174. *
  175. * @param line Handshake.
  176. */
  177. void LocalSocket::handleHandshake (QString line)
  178. {
  179. QRegularExpression re(IrGGu_IRC_Handshake::receive);
  180. QRegularExpressionMatch rem = re.match(line);
  181. if ( rem.hasMatch() )
  182. {
  183. receivedHandshake = true;
  184. versionOk = rem.captured("version").toFloat() == IrGGu_IRC::version;
  185. writeServerHandshake();
  186. }
  187. else
  188. {
  189. socket->disconnectFromServer();
  190. }
  191. }
  192. /**
  193. * Write handshake.
  194. */
  195. void LocalSocket::writeServerHandshake ()
  196. {
  197. if ( receivedHandshake )
  198. {
  199. QString version = QString::number(IrGGu_IRC::version, 10, 1);
  200. QString line = IrGGu_IRC_Handshake::write + "\n";
  201. line.replace("<version>", version);
  202. write(line.toUtf8());
  203. }
  204. }
  205. /**
  206. * Read data sent by client.
  207. */
  208. void LocalSocket::readData ()
  209. {
  210. if ( !sentHandshake )
  211. {
  212. QString line;
  213. while ( socket->canReadLine() )
  214. {
  215. line = QString::fromUtf8(socket->readLine()).trimmed();
  216. handleHandshake(line);
  217. }
  218. }
  219. else
  220. {
  221. Q_EMIT readyRead();
  222. }
  223. }
  224. /**
  225. * Called when data has been sent to client.
  226. */
  227. void LocalSocket::wroteBytes ()
  228. {
  229. if ( !sentHandshake )
  230. {
  231. if ( versionOk )
  232. {
  233. sentHandshake = true;
  234. Q_EMIT connected();
  235. }
  236. else if ( socket->bytesToWrite() == 0 )
  237. {
  238. socket->disconnectFromServer();
  239. }
  240. }
  241. else
  242. {
  243. Q_EMIT bytesWritten();
  244. }
  245. }
  246. /**
  247. * Signal is emitted when socket is in connected state.
  248. *
  249. * @fn void LocalSocket::connected()
  250. */
  251. /**
  252. * Signal is emitted when socket is in disconnected state.
  253. *
  254. * @fn void LocalSocket::disconnected()
  255. */
  256. /**
  257. * Signal is emitted when socket has data for reading.
  258. *
  259. * @fn void LocalSocket::readyRead()
  260. */
  261. /**
  262. * Signal is emitted when socket wrote data.
  263. *
  264. * @fn void LocalSocket::bytesWritten()
  265. */