Example #1
0
int Logic::createRequest(bool simple, const std::string &client, const std::string &session,
                         const std::string &user, const std::string &privilege,
                         cynara_check_id &checkId, cynara_response_callback callback,
                         void *userResponseData) {
    if (!m_operationPermitted)
        return CYNARA_API_OPERATION_NOT_ALLOWED;

    if (!ensureConnection())
        return CYNARA_API_SERVICE_NOT_AVAILABLE;

    ProtocolFrameSequenceNumber sequenceNumber;
    if (!m_sequenceContainer.get(sequenceNumber))
        return CYNARA_API_MAX_PENDING_REQUESTS;

    PolicyKey key(client, user, privilege);
    ResponseCallback responseCallback(callback, userResponseData);
    m_checks.insert(CheckPair(sequenceNumber, CheckData(key, session, responseCallback,
                                                        simple)));
    if (simple)
        m_socketClient.appendRequest(SimpleCheckRequest(key, sequenceNumber));
    else
        m_socketClient.appendRequest(CheckRequest(key, sequenceNumber));

    onStatusChange(m_socketClient.getSockFd(), cynara_async_status::CYNARA_STATUS_FOR_RW);
    checkId = static_cast<cynara_check_id>(sequenceNumber);

    return CYNARA_API_SUCCESS;
}
Example #2
0
void Logic::flushMonitor() {
    if (!m_monitoringEnabled)
        return;

    if (m_monitorCache.entries().size() == 0)
        return;

    if (!ensureConnection()) {
        LOGE("Could not flush monitor entries: connection lost");
        return;
    }

    auto flushSuccess = requestMonitorEntriesPut();
    if (flushSuccess) {
        m_monitorCache.clear();
    }
}
Example #3
0
int Logic::simpleCheck(const std::string &client, const ClientSession &session,
                       const std::string &user, const std::string &privilege) {
    if (!ensureConnection())
        return CYNARA_API_SERVICE_NOT_AVAILABLE;

    PolicyKey key(client, user, privilege);
    int ret = m_cache.get(session, key);
    if (ret != CYNARA_API_CACHE_MISS) {
        return ret;
    }

    PolicyResult result;
    ret = requestSimpleResult(key, result);
    if (ret != CYNARA_API_SUCCESS) {
        if (ret != CYNARA_API_ACCESS_NOT_RESOLVED) {
            LOGE("Error fetching response for simpleCheck.");
        }
        return ret;
    }

    return m_cache.update(session, key, result);
}
Example #4
0
int Logic::getRequest(AgentActionResponsePtr &resultPtr) {
    int ret = ensureConnection();
    if (ret != CYNARA_API_SUCCESS)
        return ret;

    ResponsePtr responsePtr = m_socketClient.getBufferedResponse();
    if (responsePtr == nullptr) {
        AgentSocketState state = m_socketClient.waitForEvent();
        switch (state) {
        case AgentSocketState::SS_QUITREQUEST:
            LOGD("Waiting interrupted. Finishing");
            m_notify.snooze();
            return CYNARA_API_INTERRUPTED;
        case AgentSocketState::SS_REQUEST:
        {
            responsePtr = m_socketClient.receiveResponseFromServer();
            if (!responsePtr) {
                LOGW("Disconnected by cynara server.");
                return CYNARA_API_SERVICE_NOT_AVAILABLE;
            }
            break;
        }
        default:
            LOGE("Wrong state returned [" << state << "]");
            return CYNARA_API_UNKNOWN_ERROR;
        }
    }
    AgentActionResponsePtr actionResponsePtr =
        std::dynamic_pointer_cast<AgentActionResponse>(responsePtr);
    if (!actionResponsePtr) {
        LOGC("Casting request to AgentActionResponse failed.");
        return CYNARA_API_UNKNOWN_ERROR;
    }
    LOGD("agentActionResponse: type: [%" PRIu8 "], data length: [%zu]",
         actionResponsePtr->type(), actionResponsePtr->data().size());

    resultPtr = actionResponsePtr;
    return CYNARA_API_SUCCESS;
}
Example #5
0
int Logic::check(const std::string &client, const ClientSession &session, const std::string &user,
                 const std::string &privilege) {
    if (!ensureConnection())
        return CYNARA_API_SERVICE_NOT_AVAILABLE;

    PolicyKey key(client, user, privilege);
    int ret = m_cache.get(session, key);
    if (ret != CYNARA_API_CACHE_MISS) {
        updateMonitor(key, ret);
        return ret;
    }

    PolicyResult result;
    ret = requestResult(key, result);
    if (ret != CYNARA_API_SUCCESS) {
        LOGE("Error fetching new entry.");
        return ret;
    }

    updateMonitor(key, ret);

    return m_cache.update(session, key, result);
}
Example #6
0
int Logic::getRequest(AgentActionResponsePtr &resultPtr) {
    int ret = ensureConnection();
    if (ret != CYNARA_API_SUCCESS)
        return ret;

    ResponsePtr responsePtr = m_socketClient.receiveResponseFromServer();
    if (!responsePtr) {
        LOGW("Disconnected by cynara server.");
        return CYNARA_API_SERVICE_NOT_AVAILABLE;
    }

    AgentActionResponsePtr actionResponsePtr =
        std::dynamic_pointer_cast<AgentActionResponse>(responsePtr);
    if (!actionResponsePtr) {
        LOGC("Casting request to AgentActionResponse failed.");
        return CYNARA_API_UNKNOWN_ERROR;
    }
    LOGD("agentActionResponse: type: [%" PRIu8 "], data length: [%zu]",
         actionResponsePtr->type(), actionResponsePtr->data().size());

    resultPtr = actionResponsePtr;
    return CYNARA_API_SUCCESS;
}
Example #7
0
int Logic::cancelRequest(cynara_check_id checkId) {
    if (!m_operationPermitted)
        return CYNARA_API_OPERATION_NOT_ALLOWED;

    if (!ensureConnection())
        return CYNARA_API_SERVICE_NOT_AVAILABLE;

    auto it = m_checks.find(checkId);
    if (it == m_checks.end() || it->second.cancelled())
        return CYNARA_API_INVALID_PARAM;

    m_socketClient.appendRequest(CancelRequest(it->first));

    it->second.cancel();

    bool onAnswerCancel = m_inAnswerCancelResponseCallback;
    m_inAnswerCancelResponseCallback = true;
    it->second.callback().onCancel(it->first);
    m_inAnswerCancelResponseCallback = onAnswerCancel;

    onStatusChange(m_socketClient.getSockFd(), cynara_async_status::CYNARA_STATUS_FOR_RW);

    return CYNARA_API_SUCCESS;
}
Example #8
0
bool QHttpNetworkConnectionChannel::sendRequest()
{
    if (!reply) {
        // heh, how should that happen!
        qWarning() << "QHttpNetworkConnectionChannel::sendRequest() called without QHttpNetworkReply";
        state = QHttpNetworkConnectionChannel::IdleState;
        return false;
    }

    switch (state) {
    case QHttpNetworkConnectionChannel::IdleState: { // write the header
        if (!ensureConnection()) {
            // wait for the connection (and encryption) to be done
            // sendRequest will be called again from either
            // _q_connected or _q_encrypted
            return false;
        }
        written = 0; // excluding the header
        bytesTotal = 0;

        QHttpNetworkReplyPrivate *replyPrivate = reply->d_func();
        replyPrivate->clear();
        replyPrivate->connection = connection;
        replyPrivate->connectionChannel = this;
        replyPrivate->autoDecompress = request.d->autoDecompress;
        replyPrivate->pipeliningUsed = false;

        // if the url contains authentication parameters, use the new ones
        // both channels will use the new authentication parameters
        if (!request.url().userInfo().isEmpty() && request.withCredentials()) {
            QUrl url = request.url();
            QAuthenticator &auth = authenticator;
            if (url.userName() != auth.user()
                || (!url.password().isEmpty() && url.password() != auth.password())) {
                auth.setUser(url.userName());
                auth.setPassword(url.password());
                connection->d_func()->copyCredentials(connection->d_func()->indexOf(socket), &auth, false);
            }
            // clear the userinfo,  since we use the same request for resending
            // userinfo in url can conflict with the one in the authenticator
            url.setUserInfo(QString());
            request.setUrl(url);
        }
        // Will only be false if QtWebKit is performing a cross-origin XMLHttpRequest
        // and withCredentials has not been set to true.
        if (request.withCredentials())
            connection->d_func()->createAuthorization(socket, request);
#ifndef QT_NO_NETWORKPROXY
        QByteArray header = QHttpNetworkRequestPrivate::header(request,
            (connection->d_func()->networkProxy.type() != QNetworkProxy::NoProxy));
#else
        QByteArray header = QHttpNetworkRequestPrivate::header(request, false);
#endif
        socket->write(header);
        // flushing is dangerous (QSslSocket calls transmit which might read or error)
//        socket->flush();
        QNonContiguousByteDevice* uploadByteDevice = request.uploadByteDevice();
        if (uploadByteDevice) {
            // connect the signals so this function gets called again
            QObject::connect(uploadByteDevice, SIGNAL(readyRead()),this, SLOT(_q_uploadDataReadyRead()));

            bytesTotal = request.contentLength();

            state = QHttpNetworkConnectionChannel::WritingState; // start writing data
            sendRequest(); //recurse
        } else {
            state = QHttpNetworkConnectionChannel::WaitingState; // now wait for response
            sendRequest(); //recurse
        }

        break;
    }
    case QHttpNetworkConnectionChannel::WritingState:
    {
        // write the data
        QNonContiguousByteDevice* uploadByteDevice = request.uploadByteDevice();
        if (!uploadByteDevice || bytesTotal == written) {
            if (uploadByteDevice)
                emit reply->dataSendProgress(written, bytesTotal);
            state = QHttpNetworkConnectionChannel::WaitingState; // now wait for response
            sendRequest(); // recurse
            break;
        }

        // only feed the QTcpSocket buffer when there is less than 32 kB in it
        const qint64 socketBufferFill = 32*1024;
        const qint64 socketWriteMaxSize = 16*1024;


#ifndef QT_NO_OPENSSL
        QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket);
        // if it is really an ssl socket, check more than just bytesToWrite()
        while ((socket->bytesToWrite() + (sslSocket ? sslSocket->encryptedBytesToWrite() : 0))
                <= socketBufferFill && bytesTotal != written)
#else
        while (socket->bytesToWrite() <= socketBufferFill
               && bytesTotal != written)
#endif
        {
            // get pointer to upload data
            qint64 currentReadSize = 0;
            qint64 desiredReadSize = qMin(socketWriteMaxSize, bytesTotal - written);
            const char *readPointer = uploadByteDevice->readPointer(desiredReadSize, currentReadSize);

            if (currentReadSize == -1) {
                // premature eof happened
                connection->d_func()->emitReplyError(socket, reply, QNetworkReply::UnknownNetworkError);
                return false;
                break;
            } else if (readPointer == 0 || currentReadSize == 0) {
                // nothing to read currently, break the loop
                break;
            } else {
                qint64 currentWriteSize = socket->write(readPointer, currentReadSize);
                if (currentWriteSize == -1 || currentWriteSize != currentReadSize) {
                    // socket broke down
                    connection->d_func()->emitReplyError(socket, reply, QNetworkReply::UnknownNetworkError);
                    return false;
                } else {
                    written += currentWriteSize;
                    uploadByteDevice->advanceReadPointer(currentWriteSize);

                    emit reply->dataSendProgress(written, bytesTotal);

                    if (written == bytesTotal) {
                        // make sure this function is called once again
                        state = QHttpNetworkConnectionChannel::WaitingState;
                        sendRequest();
                        break;
                    }
                }
            }
        }
        break;
    }

    case QHttpNetworkConnectionChannel::WaitingState:
    {
        QNonContiguousByteDevice* uploadByteDevice = request.uploadByteDevice();
        if (uploadByteDevice) {
            QObject::disconnect(uploadByteDevice, SIGNAL(readyRead()), this, SLOT(_q_uploadDataReadyRead()));
        }

        // HTTP pipelining
        //connection->d_func()->fillPipeline(socket);
        //socket->flush();

        // ensure we try to receive a reply in all cases, even if _q_readyRead_ hat not been called
        // this is needed if the sends an reply before we have finished sending the request. In that
        // case receiveReply had been called before but ignored the server reply
        if (socket->bytesAvailable())
            QMetaObject::invokeMethod(this, "_q_receiveReply", Qt::QueuedConnection);
        break;
    }
    case QHttpNetworkConnectionChannel::ReadingState:
        // ignore _q_bytesWritten in these states
        // fall through
    default:
        break;
    }
    return true;
}