Blame lang/cpp/src/eventloopinteractor.cpp

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