Line data Source code
1 : /*
2 : eventloopinteractor.cpp
3 : Copyright (C) 2003,2004 Klarälvdalens Datakonsult AB
4 : 2016 Bundesamt für Sicherheit in der Informationstechnik
5 : Software engineering by Intevation GmbH
6 :
7 : This file is part of GPGME++.
8 :
9 : GPGME++ is free software; you can redistribute it and/or
10 : modify it under the terms of the GNU Library General Public
11 : License as published by the Free Software Foundation; either
12 : version 2 of the License, or (at your option) any later version.
13 :
14 : GPGME++ is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU Library General Public License for more details.
18 :
19 : You should have received a copy of the GNU Library General Public License
20 : along with GPGME++; see the file COPYING.LIB. If not, write to the
21 : Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 : Boston, MA 02110-1301, USA.
23 : */
24 :
25 : #ifdef HAVE_CONFIG_H
26 : #include "config.h"
27 : #endif
28 :
29 : #include <eventloopinteractor.h>
30 :
31 : #include <context.h>
32 : #include "context_p.h"
33 : #include <key.h>
34 : #include <trustitem.h>
35 :
36 : #include <gpgme.h>
37 :
38 : #include <vector>
39 : using std::vector;
40 : #ifndef NDEBUG
41 : # include <iostream>
42 : #endif
43 : #include <cassert>
44 :
45 : namespace GpgME
46 : {
47 :
48 : //
49 : // EventLoopInteractor::Private Declaration
50 : //
51 :
52 0 : class EventLoopInteractor::Private
53 : {
54 : public:
55 : struct OneFD {
56 0 : OneFD(int aFd, int aDir, gpgme_io_cb_t aFnc,
57 : void *aFncData, void *aExternalTag)
58 0 : : fd(aFd), dir(aDir), fnc(aFnc),
59 0 : fncData(aFncData), externalTag(aExternalTag) {}
60 : int fd;
61 : int dir;
62 : gpgme_io_cb_t fnc;
63 : void *fncData;
64 : void *externalTag;
65 : };
66 :
67 : vector<OneFD *> mCallbacks;
68 :
69 : static void removeIOCb(void *tag);
70 : static gpgme_error_t registerIOCb(void *data, int fd, int dir,
71 : gpgme_io_cb_t fnc, void *fnc_data,
72 : void **r_tag);
73 : static void eventIOCb(void *, gpgme_event_io_t type, void *type_data);
74 :
75 : static const gpgme_io_cbs iocbs;
76 : };
77 :
78 : const gpgme_io_cbs EventLoopInteractor::Private::iocbs = {
79 : &EventLoopInteractor::Private::registerIOCb,
80 : 0,
81 : &EventLoopInteractor::Private::removeIOCb,
82 : &EventLoopInteractor::Private::eventIOCb,
83 : 0
84 : };
85 :
86 : //
87 : // EventLoopInteractor::Private IO Callback Implementations
88 : //
89 :
90 0 : gpgme_error_t EventLoopInteractor::Private::registerIOCb(void *, int fd, int dir,
91 : gpgme_io_cb_t fnc, void *fnc_data,
92 : void **r_tag)
93 : {
94 0 : assert(instance()); assert(instance()->d);
95 0 : bool ok = false;
96 0 : void *etag = instance()->registerWatcher(fd, dir ? Read : Write, ok);
97 0 : if (!ok) {
98 0 : return gpgme_error(GPG_ERR_GENERAL);
99 : }
100 0 : instance()->d->mCallbacks.push_back(new OneFD(fd, dir, fnc, fnc_data, etag));
101 0 : if (r_tag) {
102 0 : *r_tag = instance()->d->mCallbacks.back();
103 : }
104 0 : return GPG_ERR_NO_ERROR;
105 : }
106 :
107 0 : void EventLoopInteractor::Private::removeIOCb(void *tag)
108 : {
109 :
110 0 : if (!instance() || !instance()->d) {
111 0 : return;
112 : }
113 0 : for (vector<OneFD *>::iterator it = instance()->d->mCallbacks.begin();
114 0 : it != instance()->d->mCallbacks.end() ; ++it) {
115 0 : if (*it == tag) {
116 0 : instance()->unregisterWatcher((*it)->externalTag);
117 0 : delete *it; *it = 0;
118 0 : instance()->d->mCallbacks.erase(it);
119 0 : return;
120 : }
121 : }
122 : }
123 :
124 0 : void EventLoopInteractor::Private::eventIOCb(void *data, gpgme_event_io_t type, void *type_data)
125 : {
126 0 : assert(instance());
127 0 : Context *ctx = static_cast<Context *>(data);
128 0 : switch (type) {
129 : case GPGME_EVENT_START: {
130 0 : instance()->operationStartEvent(ctx);
131 : // TODO: what's in type_data?
132 : }
133 0 : break;
134 : case GPGME_EVENT_DONE: {
135 0 : gpgme_error_t e = *static_cast<gpgme_error_t *>(type_data);
136 0 : if (ctx && ctx->impl()) {
137 0 : ctx->impl()->lasterr = e;
138 : }
139 0 : instance()->operationDoneEvent(ctx, Error(e));
140 : }
141 0 : break;
142 : case GPGME_EVENT_NEXT_KEY: {
143 0 : gpgme_key_t key = static_cast<gpgme_key_t>(type_data);
144 0 : instance()->nextKeyEvent(ctx, Key(key, false));
145 : }
146 0 : break;
147 : case GPGME_EVENT_NEXT_TRUSTITEM: {
148 0 : gpgme_trust_item_t item = static_cast<gpgme_trust_item_t>(type_data);
149 0 : instance()->nextTrustItemEvent(ctx, TrustItem(item));
150 0 : gpgme_trust_item_unref(item);
151 : }
152 0 : break;
153 : default: // warn
154 : ;
155 : }
156 0 : }
157 :
158 : //
159 : // EventLoopInteractor Implementation
160 : //
161 :
162 : EventLoopInteractor *EventLoopInteractor::mSelf = 0;
163 :
164 0 : EventLoopInteractor::EventLoopInteractor() : d(new Private)
165 : {
166 0 : assert(!mSelf);
167 0 : mSelf = this;
168 0 : }
169 :
170 0 : EventLoopInteractor::~EventLoopInteractor()
171 : {
172 : // warn if there are still callbacks registered
173 0 : mSelf = 0;
174 0 : delete d;
175 0 : }
176 :
177 0 : void EventLoopInteractor::manage(Context *context)
178 : {
179 0 : if (!context || context->managedByEventLoopInteractor()) {
180 0 : return;
181 : }
182 0 : gpgme_io_cbs *iocbs = new gpgme_io_cbs(Private::iocbs);
183 0 : iocbs->event_priv = context;
184 0 : context->installIOCallbacks(iocbs);
185 : }
186 :
187 0 : void EventLoopInteractor::unmanage(Context *context)
188 : {
189 0 : if (context) {
190 0 : context->uninstallIOCallbacks();
191 : }
192 0 : }
193 :
194 0 : void EventLoopInteractor::actOn(int fd, Direction dir)
195 : {
196 0 : for (vector<Private::OneFD *>::const_iterator it = d->mCallbacks.begin();
197 0 : it != d->mCallbacks.end() ; ++it) {
198 0 : if ((*it)->fd == fd && ((*it)->dir ? Read : Write) == dir) {
199 0 : (*((*it)->fnc))((*it)->fncData, fd);
200 0 : break;
201 : }
202 : }
203 0 : }
204 :
205 24 : } // namespace GpgME
|