Warning, file /sdk/dferry/transport/iserver.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002    Copyright (C) 2014 Andreas Hartmetz <ahartmetz@gmail.com>
0003 
0004    This library is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU Library General Public
0006    License as published by the Free Software Foundation; either
0007    version 2 of the License, or (at your option) any later version.
0008 
0009    This library is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    Library General Public License for more details.
0013 
0014    You should have received a copy of the GNU Library General Public License
0015    along with this library; see the file COPYING.LGPL.  If not, write to
0016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017    Boston, MA 02110-1301, USA.
0018 
0019    Alternatively, this file is available under the Mozilla Public License
0020    Version 1.1.  You may obtain a copy of the License at
0021    http://www.mozilla.org/MPL/
0022 */
0023 
0024 #include "iserver.h"
0025 
0026 #include "connectaddress.h"
0027 #include "eventdispatcher_p.h"
0028 #include "itransport.h"
0029 #include "ipserver.h"
0030 #ifdef __unix__
0031 #include "localserver.h"
0032 #endif
0033 
0034 #include <string>
0035 #include <iostream>
0036 
0037 #ifdef __unix__
0038 #include <random>
0039 #include "stringtools.h"
0040 
0041 static std::string randomDbusSocketName()
0042 {
0043     std::random_device rd;
0044     std::mt19937 mt(rd());
0045     char randomData[16];
0046     // OK dead code elimination, show us what you can!
0047     if (sizeof(size_t) >= 8) {
0048         std::uniform_int_distribution<uint64> dist;
0049         for (size_t i = 0; i < (sizeof(randomData) / sizeof(uint64)); i++) {
0050             reinterpret_cast<uint64 *>(randomData)[i] = dist(mt);
0051         }
0052     } else {
0053         std::uniform_int_distribution<uint32> dist;
0054         for (size_t i = 0; i < (sizeof(randomData) / sizeof(uint32)); i++) {
0055             reinterpret_cast<uint32 *>(randomData)[i] = dist(mt);
0056         }
0057     }
0058     // Good that std::string knows nothing about valid utf-8 encoding!
0059     const std::string pseudoString(randomData, sizeof(randomData));
0060     return std::string("/dbus-") + hexEncode(pseudoString);
0061 }
0062 
0063 static std::string xdgRuntimeDir()
0064 {
0065     return std::string(getenv("XDG_RUNTIME_DIR"));
0066 }
0067 #endif
0068 
0069 IServer::IServer()
0070    : m_newConnectionListener(nullptr)
0071 {
0072     setIoInterest(uint32(IO::RW::Read));
0073 }
0074 
0075 IServer::~IServer()
0076 {
0077     for (ITransport *c : m_incomingConnections) {
0078         delete c;
0079     }
0080 }
0081 
0082 //static
0083 IServer *IServer::create(const ConnectAddress &listenAddr, ConnectAddress *concreteAddr)
0084 {
0085     if (listenAddr.role() != ConnectAddress::Role::PeerServer) {
0086         return nullptr;
0087     }
0088 
0089 #ifdef __unix__
0090     bool isLocalSocket = true;
0091     bool isAbstract = false;
0092     std::string unixSocketPath;
0093 #endif
0094 
0095     switch (listenAddr.type()) {
0096 #ifdef __unix__
0097     case ConnectAddress::Type::UnixPath:
0098         unixSocketPath = listenAddr.path();
0099         break;
0100     case ConnectAddress::Type::UnixDir:
0101         unixSocketPath = listenAddr.path() + randomDbusSocketName();
0102         break;
0103     case ConnectAddress::Type::RuntimeDir:
0104         unixSocketPath = xdgRuntimeDir() + randomDbusSocketName();
0105         break;
0106     case ConnectAddress::Type::TmpDir:
0107         unixSocketPath = listenAddr.path() + randomDbusSocketName();
0108 #ifdef __linux__
0109         isAbstract = true;
0110 #endif
0111         break;
0112 #ifdef __linux__
0113     case ConnectAddress::Type::AbstractUnixPath:
0114         unixSocketPath = listenAddr.path();
0115         isAbstract = true;
0116         break;
0117 #endif
0118 #endif
0119     case ConnectAddress::Type::Tcp:
0120     case ConnectAddress::Type::Tcp4:
0121     case ConnectAddress::Type::Tcp6:
0122 #ifdef __unix__
0123         isLocalSocket = false;
0124 #endif
0125         break;
0126     default:
0127         return nullptr;
0128     }
0129 
0130     *concreteAddr = listenAddr;
0131 
0132 #ifdef __unix__
0133     if (isLocalSocket) {
0134         concreteAddr->setType(isAbstract ? ConnectAddress::Type::AbstractUnixPath
0135                                          : ConnectAddress::Type::UnixPath);
0136         concreteAddr->setPath(unixSocketPath);
0137         if (isAbstract) {
0138             unixSocketPath.insert(0, 1, '\0');
0139         }
0140         return new LocalServer(unixSocketPath);
0141     } else
0142 #endif
0143         return new IpServer(listenAddr);
0144 }
0145 
0146 ITransport *IServer::takeNextClient()
0147 {
0148     if (m_incomingConnections.empty()) {
0149         return nullptr;
0150     }
0151     ITransport *ret = m_incomingConnections.front();
0152     m_incomingConnections.pop_front();
0153     return ret;
0154 }
0155 
0156 void IServer::setNewConnectionListener(ICompletionListener *listener)
0157 {
0158     m_newConnectionListener = listener;
0159 }
0160 
0161 void IServer::close()
0162 {
0163     if (!isListening()) {
0164         return;
0165     }
0166     if (ioEventSource()) {
0167         ioEventSource()->removeIoListener(this);
0168     }
0169     platformClose();
0170 }