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 : #include <eventloopinteractor.h>
24 :
25 : #include <context.h>
26 : #include "context_p.h"
27 : #include <key.h>
28 : #include <trustitem.h>
29 :
30 : #include <gpgme.h>
31 :
32 : #include <vector>
33 : using std::vector;
34 : #ifndef NDEBUG
35 : # include <iostream>
36 : #endif
37 : #include <cassert>
38 :
39 : namespace GpgME
40 : {
41 :
42 : //
43 : // EventLoopInteractor::Private Declaration
44 : //
45 :
46 0 : class EventLoopInteractor::Private
47 : {
48 : public:
49 : struct OneFD {
50 0 : OneFD(int aFd, int aDir, gpgme_io_cb_t aFnc,
51 : void *aFncData, void *aExternalTag)
52 : : fd(aFd), dir(aDir), fnc(aFnc),
53 0 : fncData(aFncData), externalTag(aExternalTag) {}
54 : int fd;
55 : int dir;
56 : gpgme_io_cb_t fnc;
57 : void *fncData;
58 : void *externalTag;
59 : };
60 :
61 : vector<OneFD *> mCallbacks;
62 :
63 : static void removeIOCb(void *tag);
64 : static gpgme_error_t registerIOCb(void *data, int fd, int dir,
65 : gpgme_io_cb_t fnc, void *fnc_data,
66 : void **r_tag);
67 : static void eventIOCb(void *, gpgme_event_io_t type, void *type_data);
68 :
69 : static const gpgme_io_cbs iocbs;
70 : };
71 :
72 : const gpgme_io_cbs EventLoopInteractor::Private::iocbs = {
73 : &EventLoopInteractor::Private::registerIOCb,
74 : 0,
75 : &EventLoopInteractor::Private::removeIOCb,
76 : &EventLoopInteractor::Private::eventIOCb,
77 : 0
78 : };
79 :
80 : //
81 : // EventLoopInteractor::Private IO Callback Implementations
82 : //
83 :
84 0 : gpgme_error_t EventLoopInteractor::Private::registerIOCb(void *, int fd, int dir,
85 : gpgme_io_cb_t fnc, void *fnc_data,
86 : void **r_tag)
87 : {
88 0 : assert(instance()); assert(instance()->d);
89 0 : bool ok = false;
90 0 : void *etag = instance()->registerWatcher(fd, dir ? Read : Write, ok);
91 0 : if (!ok) {
92 0 : return gpgme_error(GPG_ERR_GENERAL);
93 : }
94 0 : instance()->d->mCallbacks.push_back(new OneFD(fd, dir, fnc, fnc_data, etag));
95 0 : if (r_tag) {
96 0 : *r_tag = instance()->d->mCallbacks.back();
97 : }
98 0 : return GPG_ERR_NO_ERROR;
99 : }
100 :
101 0 : void EventLoopInteractor::Private::removeIOCb(void *tag)
102 : {
103 :
104 0 : if (!instance() || !instance()->d) {
105 0 : return;
106 : }
107 0 : for (vector<OneFD *>::iterator it = instance()->d->mCallbacks.begin();
108 0 : it != instance()->d->mCallbacks.end() ; ++it) {
109 0 : if (*it == tag) {
110 0 : instance()->unregisterWatcher((*it)->externalTag);
111 0 : delete *it; *it = 0;
112 0 : instance()->d->mCallbacks.erase(it);
113 0 : return;
114 : }
115 : }
116 : }
117 :
118 0 : void EventLoopInteractor::Private::eventIOCb(void *data, gpgme_event_io_t type, void *type_data)
119 : {
120 0 : assert(instance());
121 0 : Context *ctx = static_cast<Context *>(data);
122 0 : switch (type) {
123 : case GPGME_EVENT_START: {
124 0 : instance()->operationStartEvent(ctx);
125 : // TODO: what's in type_data?
126 : }
127 0 : break;
128 : case GPGME_EVENT_DONE: {
129 0 : gpgme_error_t e = *static_cast<gpgme_error_t *>(type_data);
130 0 : if (ctx && ctx->impl()) {
131 0 : ctx->impl()->lasterr = e;
132 : }
133 0 : instance()->operationDoneEvent(ctx, Error(e));
134 : }
135 0 : break;
136 : case GPGME_EVENT_NEXT_KEY: {
137 0 : gpgme_key_t key = static_cast<gpgme_key_t>(type_data);
138 0 : instance()->nextKeyEvent(ctx, Key(key, false));
139 : }
140 0 : break;
141 : case GPGME_EVENT_NEXT_TRUSTITEM: {
142 0 : gpgme_trust_item_t item = static_cast<gpgme_trust_item_t>(type_data);
143 0 : instance()->nextTrustItemEvent(ctx, TrustItem(item));
144 0 : gpgme_trust_item_unref(item);
145 : }
146 0 : break;
147 : default: // warn
148 : ;
149 : }
150 0 : }
151 :
152 : //
153 : // EventLoopInteractor Implementation
154 : //
155 :
156 : EventLoopInteractor *EventLoopInteractor::mSelf = 0;
157 :
158 0 : EventLoopInteractor::EventLoopInteractor() : d(new Private)
159 : {
160 0 : assert(!mSelf);
161 0 : mSelf = this;
162 0 : }
163 :
164 0 : EventLoopInteractor::~EventLoopInteractor()
165 : {
166 : // warn if there are still callbacks registered
167 0 : mSelf = 0;
168 0 : delete d;
169 0 : }
170 :
171 0 : void EventLoopInteractor::manage(Context *context)
172 : {
173 0 : if (!context || context->managedByEventLoopInteractor()) {
174 0 : return;
175 : }
176 0 : gpgme_io_cbs *iocbs = new gpgme_io_cbs(Private::iocbs);
177 0 : iocbs->event_priv = context;
178 0 : context->installIOCallbacks(iocbs);
179 : }
180 :
181 0 : void EventLoopInteractor::unmanage(Context *context)
182 : {
183 0 : if (context) {
184 0 : context->uninstallIOCallbacks();
185 : }
186 0 : }
187 :
188 0 : void EventLoopInteractor::actOn(int fd, Direction dir)
189 : {
190 0 : for (vector<Private::OneFD *>::const_iterator it = d->mCallbacks.begin();
191 0 : it != d->mCallbacks.end() ; ++it) {
192 0 : if ((*it)->fd == fd && ((*it)->dir ? Read : Write) == dir) {
193 0 : (*((*it)->fnc))((*it)->fncData, fd);
194 0 : break;
195 : }
196 : }
197 0 : }
198 :
199 18 : } // namespace GpgME
|