void ForkExecChild::connect()
{
    // set error state, clear it later
    m_state = DISCONNECTED;

    const char *address = getParentDBusAddress();
    if (!address) {
        SE_THROW("cannot connect to parent, was not forked");
    }

    SE_LOG_DEBUG(NULL, NULL, "ForkExecChild: connecting to parent with D-Bus address %s",
                 address);
    GDBusCXX::DBusErrorCXX dbusError;
    GDBusCXX::DBusConnectionPtr conn = dbus_get_bus_connection(address,
                                                               &dbusError,
                                                               true /* always delay message processing */);
    if (!conn) {
        dbusError.throwFailure("connecting to server");
    }

    m_state = CONNECTED;

    // start watching connection
#ifdef GDBUS_CXX_HAVE_DISCONNECT
    conn.setDisconnect(boost::bind(&ForkExecChild::connectionLost, this));
#else
    // emulate disconnect with a pending method call
    class Parent : public GDBusCXX::DBusRemoteObject
    {
    public:
        Parent(const GDBusCXX::DBusConnectionPtr &conn) :
            GDBusCXX::DBusRemoteObject(conn,
                                       FORKEXEC_PARENT_PATH,
                                       FORKEXEC_PARENT_IFACE,
                                       FORKEXEC_PARENT_DESTINATION),
            m_watch(*this, "Watch")
        {}

        GDBusCXX::DBusClientCall0 m_watch;
    } parent(conn);
    parent.m_watch.start(boost::bind(&ForkExecChild::connectionLost, this));
#endif

    m_onConnect(conn);
    dbus_bus_connection_undelay(conn);
}
void ForkExecParent::newClientConnection(GDBusCXX::DBusConnectionPtr &conn) throw()
{
    try {
        SE_LOG_DEBUG(NULL, NULL, "ForkExecParent: child %s has connected",
                     m_helper.c_str());
        m_hasConnected = true;
#ifndef GDBUS_CXX_HAVE_DISCONNECT
        m_api.reset(new ForkExecParentDBusAPI(conn));
#endif
        m_onConnect(conn);
    } catch (...) {
        std::string explanation;
        SyncMLStatus status = Exception::handle(explanation);
        try {
            m_onFailure(status, explanation);
        } catch (...) {
            Exception::handle();
        }
    }
}
Exemple #3
0
    void SocketServer::run(std::mutex& mutex)
    {
        bool alive = true;
        while (alive)
        {
            bool performedRead = false;
            bool performedWrite = false;

            {
                std::lock_guard<std::mutex> m(mutex);
                alive = m_alive;
            }
            if (!alive)
                break;

            fd_set reader;
            fd_set writer;
            FD_ZERO(&reader);
            FD_ZERO(&writer);

            // set server socket
            FD_SET(m_serverSocket->m_socket, &reader);
            if(m_serverSocket->m_data.size() > 0)
                FD_SET(m_serverSocket->m_socket, &writer);

            // set client sockets
            for (auto&& sock : m_clients)
            {
                FD_SET(sock.socket->m_socket, &reader);
                if(sock.socket->m_data.size() > 0)
                //if (sock->hasData())
                    FD_SET(sock.socket->m_socket, &writer);
            }

            timeval time;
            time.tv_sec = 0;
            time.tv_usec = 1000; // 500 ms
            auto changedSockets = select(0, &reader, &writer, nullptr, &time);
            if (changedSockets == SOCKET_ERROR)
                LOG_ERROR("Socket select failed");

            // check for new connections
            if (FD_ISSET(m_serverSocket->m_socket, &reader))
            {
                if(!m_broadcasting)
                {
                    // new connection
                    LOG_WARNING("SocketServer got a new connection");
                    m_clients.emplace_back(ClientContainer{
                        std::make_shared<PrefixLengthMessageParser>(m_onData),
                        std::shared_ptr<Socket>(
                        new Socket(accept(m_serverSocket->m_socket, 0, 0)),
                        [](Socket* ptr) { if(ptr->m_socket != INVALID_SOCKET)
                        { closesocket(ptr->m_socket); } delete ptr; })});

                    SocketServer::ClientContainer& client = m_clients.back();
                    if (client.socket->m_socket == INVALID_SOCKET)
                    {
                        LOG_ERROR("Client socket failed");
                        m_clients.pop_back();
                    }
                    else
                    {
                        client.parser->setSocket(client.socket);
                        client.socket->enableSocketReuse();
                        client.socket->enableNoDelay();
                        client.socket->enableNonBlockingSocket();
                        if (m_onConnect)
                            m_onConnect(client.socket);
                    }
                }
                else
                {
                    auto dataSize = m_serverSocket->dataAvailableInSocket();
                    if (dataSize > 0)
                    {
                        //LOG_INFO("got data: %i", static_cast<int>(dataSize));
                        std::vector<char> buffer(dataSize);
                        auto readBytes = m_serverSocket->read(&buffer[0], dataSize);
                        m_serverSocketParser.onData(m_serverSocket, &buffer[0], readBytes);
                        performedRead = true;
                        //client.parser->onData(client.socket, &buffer[0], readBytes);
                    }
                }
            }

            // perform client reads/writes
            std::vector<ClientContainer> remove;
            for (auto&& client : m_clients)
            {
                if (FD_ISSET(client.socket->m_socket, &reader))
                {
                    size_t bytesRead = 0;
                    auto dataSize = client.socket->dataAvailableInSocket();
                    std::vector<char> buffer(dataSize);
                    while(bytesRead < dataSize)
                    {
                        //LOG_INFO("got data: %i", static_cast<int>(dataSize));
                        
                        bytesRead += client.socket->read(&buffer[bytesRead], dataSize - bytesRead);
                        
                        performedRead = true;
                    }
                    ASSERT(bytesRead == dataSize, "Something went bad");
                    if(bytesRead > 0)
                        client.parser->onData(client.socket, &buffer[0], bytesRead);
                    
                    if(dataSize == 0)
                    {
                        //LOG_INFO("got 0 packet");
                        // client disconnected
                        remove.emplace_back(client);
                    }
                }
                if (FD_ISSET(client.socket->m_socket, &writer))
                {
                    if(client.socket->private_write() > 0)
                        performedWrite = true;
                }
            }
            /*while (remove.size() > 0)
            {
                auto sock = remove.back();
                if (m_onDisconnect)
                    m_onDisconnect(sock.socket);
                remove.pop_back();
                for (auto iter = m_clients.begin(); iter != m_clients.end(); ++iter)
                {
                    if ((*iter).socket == sock.socket)
                    {
                        m_clients.erase(iter);
                        break;
                    }
                }
                
            }*/

            if (!performedRead && !performedWrite)
            {
                std::this_thread::sleep_for(std::chrono::milliseconds(200));
            }
        }
    }