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