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