Blame lang/cpp/src/eventloopinteractor.cpp

Packit d7e8d0
/*
Packit d7e8d0
  eventloopinteractor.cpp
Packit d7e8d0
  Copyright (C) 2003,2004 Klarälvdalens Datakonsult AB
Packit d7e8d0
  2016 Bundesamt für Sicherheit in der Informationstechnik
Packit d7e8d0
  Software engineering by Intevation GmbH
Packit d7e8d0
Packit d7e8d0
  This file is part of GPGME++.
Packit d7e8d0
Packit d7e8d0
  GPGME++ is free software; you can redistribute it and/or
Packit d7e8d0
  modify it under the terms of the GNU Library General Public
Packit d7e8d0
  License as published by the Free Software Foundation; either
Packit d7e8d0
  version 2 of the License, or (at your option) any later version.
Packit d7e8d0
Packit d7e8d0
  GPGME++ is distributed in the hope that it will be useful,
Packit d7e8d0
  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit d7e8d0
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit d7e8d0
  GNU Library General Public License for more details.
Packit d7e8d0
Packit d7e8d0
  You should have received a copy of the GNU Library General Public License
Packit d7e8d0
  along with GPGME++; see the file COPYING.LIB.  If not, write to the
Packit d7e8d0
  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Packit d7e8d0
  Boston, MA 02110-1301, USA.
Packit d7e8d0
*/
Packit d7e8d0
Packit d7e8d0
#ifdef HAVE_CONFIG_H
Packit d7e8d0
 #include "config.h"
Packit d7e8d0
#endif
Packit d7e8d0
Packit d7e8d0
#include <eventloopinteractor.h>
Packit d7e8d0
Packit d7e8d0
#include <context.h>
Packit d7e8d0
#include "context_p.h"
Packit d7e8d0
#include <key.h>
Packit d7e8d0
#include <trustitem.h>
Packit d7e8d0
Packit d7e8d0
#include <gpgme.h>
Packit d7e8d0
Packit d7e8d0
#include <vector>
Packit d7e8d0
using std::vector;
Packit d7e8d0
#ifndef NDEBUG
Packit d7e8d0
# include <iostream>
Packit d7e8d0
#endif
Packit d7e8d0
#include <cassert>
Packit d7e8d0
Packit d7e8d0
namespace GpgME
Packit d7e8d0
{
Packit d7e8d0
Packit d7e8d0
//
Packit d7e8d0
// EventLoopInteractor::Private Declaration
Packit d7e8d0
//
Packit d7e8d0
Packit d7e8d0
class EventLoopInteractor::Private
Packit d7e8d0
{
Packit d7e8d0
public:
Packit d7e8d0
    struct OneFD {
Packit d7e8d0
        OneFD(int aFd, int aDir, gpgme_io_cb_t aFnc,
Packit d7e8d0
              void *aFncData, void *aExternalTag)
Packit d7e8d0
            : fd(aFd), dir(aDir), fnc(aFnc),
Packit d7e8d0
              fncData(aFncData), externalTag(aExternalTag) {}
Packit d7e8d0
        int fd;
Packit d7e8d0
        int dir;
Packit d7e8d0
        gpgme_io_cb_t fnc;
Packit d7e8d0
        void *fncData;
Packit d7e8d0
        void *externalTag;
Packit d7e8d0
    };
Packit d7e8d0
Packit d7e8d0
    vector<OneFD *> mCallbacks;
Packit d7e8d0
Packit d7e8d0
    static void removeIOCb(void *tag);
Packit d7e8d0
    static gpgme_error_t registerIOCb(void *data, int fd, int dir,
Packit d7e8d0
                                      gpgme_io_cb_t fnc, void *fnc_data,
Packit d7e8d0
                                      void **r_tag);
Packit d7e8d0
    static void eventIOCb(void *, gpgme_event_io_t type, void *type_data);
Packit d7e8d0
Packit d7e8d0
    static const gpgme_io_cbs iocbs;
Packit d7e8d0
};
Packit d7e8d0
Packit d7e8d0
const gpgme_io_cbs EventLoopInteractor::Private::iocbs = {
Packit d7e8d0
    &EventLoopInteractor::Private::registerIOCb,
Packit d7e8d0
    0,
Packit d7e8d0
    &EventLoopInteractor::Private::removeIOCb,
Packit d7e8d0
    &EventLoopInteractor::Private::eventIOCb,
Packit d7e8d0
    0
Packit d7e8d0
};
Packit d7e8d0
Packit d7e8d0
//
Packit d7e8d0
// EventLoopInteractor::Private IO Callback Implementations
Packit d7e8d0
//
Packit d7e8d0
Packit d7e8d0
gpgme_error_t EventLoopInteractor::Private::registerIOCb(void *, int fd, int dir,
Packit d7e8d0
        gpgme_io_cb_t fnc, void *fnc_data,
Packit d7e8d0
        void **r_tag)
Packit d7e8d0
{
Packit d7e8d0
    assert(instance()); assert(instance()->d);
Packit d7e8d0
    bool ok = false;
Packit d7e8d0
    void *etag = instance()->registerWatcher(fd, dir ? Read : Write, ok);
Packit d7e8d0
    if (!ok) {
Packit d7e8d0
        return gpgme_error(GPG_ERR_GENERAL);
Packit d7e8d0
    }
Packit d7e8d0
    instance()->d->mCallbacks.push_back(new OneFD(fd, dir, fnc, fnc_data, etag));
Packit d7e8d0
    if (r_tag) {
Packit d7e8d0
        *r_tag = instance()->d->mCallbacks.back();
Packit d7e8d0
    }
Packit d7e8d0
    return GPG_ERR_NO_ERROR;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
void EventLoopInteractor::Private::removeIOCb(void *tag)
Packit d7e8d0
{
Packit d7e8d0
Packit d7e8d0
    if (!instance() || !instance()->d) {
Packit d7e8d0
        return;
Packit d7e8d0
    }
Packit d7e8d0
    for (vector<OneFD *>::iterator it = instance()->d->mCallbacks.begin();
Packit d7e8d0
            it != instance()->d->mCallbacks.end() ; ++it) {
Packit d7e8d0
        if (*it == tag) {
Packit d7e8d0
            instance()->unregisterWatcher((*it)->externalTag);
Packit d7e8d0
            delete *it; *it = 0;
Packit d7e8d0
            instance()->d->mCallbacks.erase(it);
Packit d7e8d0
            return;
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
void EventLoopInteractor::Private::eventIOCb(void *data, gpgme_event_io_t type, void *type_data)
Packit d7e8d0
{
Packit d7e8d0
    assert(instance());
Packit d7e8d0
    Context *ctx = static_cast<Context *>(data);
Packit d7e8d0
    switch (type) {
Packit d7e8d0
    case GPGME_EVENT_START: {
Packit d7e8d0
        instance()->operationStartEvent(ctx);
Packit d7e8d0
        // TODO: what's in type_data?
Packit d7e8d0
    }
Packit d7e8d0
    break;
Packit d7e8d0
    case GPGME_EVENT_DONE: {
Packit d7e8d0
        gpgme_error_t e = *static_cast<gpgme_error_t *>(type_data);
Packit d7e8d0
        if (ctx && ctx->impl()) {
Packit d7e8d0
            ctx->impl()->lasterr = e;
Packit d7e8d0
        }
Packit d7e8d0
        instance()->operationDoneEvent(ctx, Error(e));
Packit d7e8d0
    }
Packit d7e8d0
    break;
Packit d7e8d0
    case GPGME_EVENT_NEXT_KEY: {
Packit d7e8d0
        gpgme_key_t key = static_cast<gpgme_key_t>(type_data);
Packit d7e8d0
        instance()->nextKeyEvent(ctx, Key(key, false));
Packit d7e8d0
    }
Packit d7e8d0
    break;
Packit d7e8d0
    case GPGME_EVENT_NEXT_TRUSTITEM: {
Packit d7e8d0
        gpgme_trust_item_t item = static_cast<gpgme_trust_item_t>(type_data);
Packit d7e8d0
        instance()->nextTrustItemEvent(ctx, TrustItem(item));
Packit d7e8d0
        gpgme_trust_item_unref(item);
Packit d7e8d0
    }
Packit d7e8d0
    break;
Packit d7e8d0
    default: // warn
Packit d7e8d0
        ;
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
//
Packit d7e8d0
// EventLoopInteractor Implementation
Packit d7e8d0
//
Packit d7e8d0
Packit d7e8d0
EventLoopInteractor *EventLoopInteractor::mSelf = 0;
Packit d7e8d0
Packit d7e8d0
EventLoopInteractor::EventLoopInteractor() : d(new Private)
Packit d7e8d0
{
Packit d7e8d0
    assert(!mSelf);
Packit d7e8d0
    mSelf = this;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
EventLoopInteractor::~EventLoopInteractor()
Packit d7e8d0
{
Packit d7e8d0
    // warn if there are still callbacks registered
Packit d7e8d0
    mSelf = 0;
Packit d7e8d0
    delete d;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
void EventLoopInteractor::manage(Context *context)
Packit d7e8d0
{
Packit d7e8d0
    if (!context || context->managedByEventLoopInteractor()) {
Packit d7e8d0
        return;
Packit d7e8d0
    }
Packit d7e8d0
    gpgme_io_cbs *iocbs = new gpgme_io_cbs(Private::iocbs);
Packit d7e8d0
    iocbs->event_priv = context;
Packit d7e8d0
    context->installIOCallbacks(iocbs);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
void EventLoopInteractor::unmanage(Context *context)
Packit d7e8d0
{
Packit d7e8d0
    if (context) {
Packit d7e8d0
        context->uninstallIOCallbacks();
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
void EventLoopInteractor::actOn(int fd, Direction dir)
Packit d7e8d0
{
Packit d7e8d0
    for (vector<Private::OneFD *>::const_iterator it = d->mCallbacks.begin();
Packit d7e8d0
            it != d->mCallbacks.end() ; ++it) {
Packit d7e8d0
        if ((*it)->fd == fd && ((*it)->dir ? Read : Write) == dir) {
Packit d7e8d0
            (*((*it)->fnc))((*it)->fncData, fd);
Packit d7e8d0
            break;
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
} // namespace GpgME