~ubuntu-branches/debian/sid/openchange/sid

« back to all changes in this revision

Viewing changes to mapiproxy/libmapistore/mgmt/mapistore_mgmt_messages.c

  • Committer: Package Import Robot
  • Author(s): Jelmer Vernooij
  • Date: 2012-04-12 20:07:57 UTC
  • mfrom: (11 sid)
  • mto: This revision was merged to the branch mainline in revision 12.
  • Revision ID: package-import@ubuntu.com-20120412200757-k933d9trljmxj1l4
Tags: 1:1.0-4
* openchangeserver: Add dependency on openchangeproxy.
* Rebuild against newer version of Samba 4.
* Use dpkg-buildflags.
* Migrate to Git, update Vcs-Git header.
* Switch to debhelper 9.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   OpenChange Storage Abstraction Layer library
 
3
 
 
4
   OpenChange Project
 
5
 
 
6
   Copyright (C) Julien Kerihuel 2011
 
7
 
 
8
   This program is free software; you can redistribute it and/or modify
 
9
   it under the terms of the GNU General Public License as published by
 
10
   the Free Software Foundation; either version 3 of the License, or
 
11
   (at your option) any later version.
 
12
   
 
13
   This program is distributed in the hope that it will be useful,
 
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
   GNU General Public License for more details.
 
17
   
 
18
   You should have received a copy of the GNU General Public License
 
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
20
 */
 
21
 
 
22
/**
 
23
   \file mapistore_mgmt_messages.c
 
24
 
 
25
   \brief Process IPC messages received on command message queue.
 
26
 */
 
27
 
 
28
#include "mapiproxy/libmapistore/mapistore.h"
 
29
#include "mapiproxy/libmapistore/mapistore_errors.h"
 
30
#include "mapiproxy/libmapistore/mapistore_private.h"
 
31
#include "mapiproxy/libmapistore/mgmt/mapistore_mgmt.h"
 
32
#include "mapiproxy/libmapistore/mgmt/gen_ndr/ndr_mapistore_mgmt.h"
 
33
 
 
34
static enum mapistore_error mapistore_mgmt_message_user_command_add(struct mapistore_mgmt_context *mgmt_ctx,
 
35
                                                                    struct mapistore_mgmt_user_cmd user_cmd,
 
36
                                                                    bool populated)
 
37
{
 
38
        struct mapistore_mgmt_users     *el;
 
39
 
 
40
        el = talloc_zero((TALLOC_CTX *)mgmt_ctx, struct mapistore_mgmt_users);
 
41
        if (!el) {
 
42
                DEBUG(0, ("[%s:%d]: Not enough memory\n", __FUNCTION__, __LINE__));
 
43
                return MAPISTORE_ERR_NO_MEMORY;
 
44
        }
 
45
        el->info = talloc_zero((TALLOC_CTX *)el, struct mapistore_mgmt_user_cmd);
 
46
        if (!el->info) {
 
47
                talloc_free(el);
 
48
                DEBUG(0, ("[%s:%d]: Not enough memory\n", __FUNCTION__, __LINE__));
 
49
                return MAPISTORE_ERR_NO_MEMORY;
 
50
        }
 
51
        if (populated == true) {
 
52
                el->info->backend = talloc_strdup((TALLOC_CTX *)el->info, user_cmd.backend);
 
53
                el->info->vuser = talloc_strdup((TALLOC_CTX *)el->info, user_cmd.vuser);
 
54
        } else {
 
55
                el->info->backend = NULL;
 
56
                el->info->vuser = NULL;
 
57
        }
 
58
        el->info->username = talloc_strdup((TALLOC_CTX *)el->info, user_cmd.username);
 
59
        el->ref_count = 1;
 
60
        el->notify_ctx = NULL;
 
61
 
 
62
        DLIST_ADD_END(mgmt_ctx->users, el, struct mapistore_mgmt_users);
 
63
 
 
64
        return MAPISTORE_SUCCESS;
 
65
}
 
66
 
 
67
enum mapistore_error mapistore_mgmt_message_user_command(struct mapistore_mgmt_context *mgmt_ctx,
 
68
                                                         struct mapistore_mgmt_user_cmd user_cmd)
 
69
{
 
70
        struct mapistore_mgmt_users     *el;
 
71
        bool                            found = false;
 
72
 
 
73
        /* Sanity checks */
 
74
        MAPISTORE_RETVAL_IF(!mgmt_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
 
75
        MAPISTORE_RETVAL_IF(user_cmd.backend == NULL || user_cmd.username == NULL || 
 
76
                            user_cmd.vuser == NULL, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
 
77
 
 
78
        if (mgmt_ctx->users == NULL) {
 
79
                if (user_cmd.status == MAPISTORE_MGMT_REGISTER) {
 
80
                        return mapistore_mgmt_message_user_command_add(mgmt_ctx, user_cmd, true);
 
81
                } else {
 
82
                        DEBUG(0, ("[%s:%d]: Trying to unregister user %s in empty list\n", 
 
83
                                  __FUNCTION__, __LINE__, user_cmd.username));
 
84
                        return MAPISTORE_SUCCESS;
 
85
                }
 
86
        } else {
 
87
                /* Search users list and perform action */
 
88
                for (el = mgmt_ctx->users; el; el = el->next) {
 
89
                        /* Case where username exists but record is incomplete */
 
90
                        if (!strcmp(el->info->username, user_cmd.username) && 
 
91
                            !el->info->backend && !el->info->vuser) {
 
92
                                found = true;
 
93
                                switch (user_cmd.status) {
 
94
                                case MAPISTORE_MGMT_REGISTER:
 
95
                                        el->info->backend = talloc_strdup((TALLOC_CTX *)el->info, user_cmd.backend);
 
96
                                        el->info->vuser = talloc_strdup((TALLOC_CTX *)el->info, user_cmd.vuser);
 
97
                                        break;
 
98
                                case MAPISTORE_MGMT_UNREGISTER:
 
99
                                        el->ref_count -= 1;
 
100
                                        /* Delete record if ref_count is 0 */
 
101
                                        if (el->ref_count == 0) {
 
102
                                                DLIST_REMOVE(mgmt_ctx->users, el);
 
103
                                                talloc_free(el);
 
104
                                                break;
 
105
                                        }
 
106
                                        break;
 
107
                                case MAPISTORE_MGMT_SEND:
 
108
                                        break;
 
109
                                }
 
110
                        }
 
111
                        /* Case where the record exists */
 
112
                        if ((!strcmp(el->info->backend, user_cmd.backend)) &&
 
113
                            (!strcmp(el->info->username, user_cmd.username)) &&
 
114
                            (!strcmp(el->info->vuser, user_cmd.vuser))) {
 
115
                                found = true;
 
116
                                switch (user_cmd.status) {
 
117
                                case MAPISTORE_MGMT_REGISTER:
 
118
                                        el->ref_count += 1;
 
119
                                        break;
 
120
                                case MAPISTORE_MGMT_UNREGISTER:
 
121
                                        el->ref_count -= 1;
 
122
                                        /* Delete record if ref_count is 0 */
 
123
                                        if (el->ref_count == 0) {
 
124
                                                DLIST_REMOVE(mgmt_ctx->users, el);
 
125
                                                talloc_free(el);
 
126
                                                break;
 
127
                                        }
 
128
                                        break;
 
129
                                default:
 
130
                                        DEBUG(0, ("[%s:%d]: Invalid user command status: %d\n",
 
131
                                                  __FUNCTION__, __LINE__, user_cmd.status));
 
132
                                        break;
 
133
                                }
 
134
                        }
 
135
                }
 
136
                /* Case where no matching record was found: insert */
 
137
                if (found == false) {
 
138
                        switch (user_cmd.status) {
 
139
                        case MAPISTORE_MGMT_REGISTER:
 
140
                                return mapistore_mgmt_message_user_command_add(mgmt_ctx, user_cmd, true);
 
141
                                break;
 
142
                        case MAPISTORE_MGMT_UNREGISTER:
 
143
                                DEBUG(0, ("[%s:%d]: Trying to unregister non-existing users %s\n",
 
144
                                          __FUNCTION__, __LINE__, user_cmd.username));
 
145
                                break;
 
146
                        default:
 
147
                                DEBUG(0, ("[%s:%d]: Invalid user command status: %d\n",
 
148
                                          __FUNCTION__, __LINE__, user_cmd.status));
 
149
                                break;
 
150
                        }
 
151
                }
 
152
        }
 
153
 
 
154
        return MAPISTORE_SUCCESS;
 
155
}
 
156
 
 
157
enum mapistore_error mapistore_mgmt_message_bind_command(struct mapistore_mgmt_context *mgmt_ctx,
 
158
                                                         struct mapistore_mgmt_bind_cmd bind)
 
159
{
 
160
        struct mapistore_mgmt_users     *el;
 
161
        bool                            found = false;
 
162
        struct mapistore_mgmt_user_cmd  user_cmd;
 
163
 
 
164
        /* Sanity checks */
 
165
        MAPISTORE_RETVAL_IF(!mgmt_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
 
166
        MAPISTORE_RETVAL_IF(!bind.username, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
 
167
        MAPISTORE_RETVAL_IF(!bind.cbContext || !bind.cbCallbackAddress, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
 
168
        
 
169
        /* If bind occurs before any user registration */
 
170
        if (!mgmt_ctx->users) {
 
171
                user_cmd.username = bind.username;
 
172
                mapistore_mgmt_message_user_command_add(mgmt_ctx, user_cmd, false);
 
173
        }
 
174
 
 
175
        for (el = mgmt_ctx->users; el; el = el->next) {
 
176
                if (!strcmp(el->info->username, bind.username)) {
 
177
                        /* Return existing notify context when existing */
 
178
                        if (el->notify_ctx) {
 
179
                                talloc_free(el->notify_ctx);
 
180
                        } 
 
181
                        found = true;
 
182
                        el->notify_ctx = talloc_zero((TALLOC_CTX *)el, struct mapistore_mgmt_notify_context);
 
183
                        el->notify_ctx->context_len = bind.cbContext;
 
184
                        el->notify_ctx->context_data = talloc_memdup((TALLOC_CTX *)el->notify_ctx, 
 
185
                                                                     bind.rgbContext, bind.cbContext);
 
186
                        el->notify_ctx->addr = talloc_memdup((TALLOC_CTX *)el->notify_ctx,
 
187
                                                             bind.rgbCallbackAddress, 
 
188
                                                             bind.cbCallbackAddress);
 
189
                        
 
190
                        /* socket / connect calls */
 
191
#ifdef SOCK_NONBLOCK
 
192
                        el->notify_ctx->fd = socket(PF_INET, SOCK_DGRAM|SOCK_NONBLOCK, IPPROTO_UDP);
 
193
#else /* SOCK_NONBLOCK */
 
194
                        {
 
195
                                int flags;
 
196
                                el->notify_ctx->fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
 
197
                                flags = fcntl(el->notify_ctx->fd, F_GETFL, 0);
 
198
                                fcntl(el->notify_ctx->fd, F_SETFL, flags | O_NONBLOCK);
 
199
                        }
 
200
#endif /* SOCK_NONBLOCK */
 
201
 
 
202
                        if (el->notify_ctx->fd == -1) {
 
203
                                perror("socket");
 
204
                                talloc_free(el->notify_ctx);
 
205
                                found = false;
 
206
                        } else {
 
207
                                if (connect(el->notify_ctx->fd, el->notify_ctx->addr, sizeof (struct sockaddr)) == -1) {
 
208
                                        perror("connect");
 
209
                                        talloc_free(el->notify_ctx);
 
210
                                        found = false;
 
211
                                }
 
212
                        }
 
213
                }
 
214
        }
 
215
 
 
216
        return (found == true) ? MAPISTORE_SUCCESS : MAPISTORE_ERR_NOT_FOUND;
 
217
}
 
218
 
 
219
static enum mapistore_error mapistore_mgmt_message_notification_command_add(struct mapistore_mgmt_users *user_cmd,
 
220
                                                                            struct mapistore_mgmt_notification_cmd notif)
 
221
{
 
222
        struct mapistore_mgmt_notif     *el;
 
223
 
 
224
        el = talloc_zero((TALLOC_CTX *)user_cmd, struct mapistore_mgmt_notif);
 
225
        if (!el) {
 
226
                DEBUG(0, ("[%s:%d]: Not enough memory\n", __FUNCTION__, __LINE__));
 
227
                return MAPISTORE_ERR_NO_MEMORY;
 
228
        }
 
229
        el->WholeStore = notif.WholeStore;
 
230
        el->NotificationFlags = notif.NotificationFlags;
 
231
 
 
232
        el->ref_count = 1;
 
233
        if (el->WholeStore == false) {
 
234
                el->MAPIStoreURI = talloc_strdup((TALLOC_CTX *)el, notif.MAPIStoreURI);
 
235
                el->FolderID = notif.FolderID;
 
236
                el->MessageID = notif.MessageID;
 
237
        }
 
238
        DLIST_ADD_END(user_cmd->notifications, el, struct mapistore_mgmt_notif);
 
239
 
 
240
        return MAPISTORE_SUCCESS;
 
241
}
 
242
 
 
243
static bool mapistore_mgmt_message_notification_wholestore(struct mapistore_mgmt_users *user_cmd,
 
244
                                                           struct mapistore_mgmt_notification_cmd notif)
 
245
{
 
246
        struct mapistore_mgmt_notif     *el;
 
247
        bool                            found = false;
 
248
 
 
249
        if (notif.WholeStore == false) return false;
 
250
 
 
251
        switch (notif.status) {
 
252
        case MAPISTORE_MGMT_REGISTER:
 
253
                for (el = user_cmd->notifications; el; el = el->next) {
 
254
                        if ((el->WholeStore == true) && 
 
255
                            (el->NotificationFlags == notif.NotificationFlags)) {
 
256
                                found = true;
 
257
                                el->ref_count += 1;
 
258
                                break;
 
259
                        }
 
260
                }
 
261
                if (found == false) {
 
262
                        mapistore_mgmt_message_notification_command_add(user_cmd, notif);
 
263
                }
 
264
                break;
 
265
        case MAPISTORE_MGMT_UNREGISTER:
 
266
                for (el = user_cmd->notifications; el; el = el->next) {
 
267
                        if ((el->WholeStore == true) &&
 
268
                            (el->NotificationFlags == notif.NotificationFlags)) {
 
269
                                el->ref_count -= 1;
 
270
                                if (!el->ref_count) {
 
271
                                        DEBUG(0, ("[%s:%d]: Deleting WholeStore subscription\n", 
 
272
                                                  __FUNCTION__, __LINE__));
 
273
                                        DLIST_REMOVE(user_cmd->notifications, el);
 
274
                                        talloc_free(el);
 
275
                                        return true;
 
276
                                }
 
277
                        }
 
278
                }
 
279
                DEBUG(0, ("[%s:%d]: Unregistered subscription found\n", __FUNCTION__, __LINE__));
 
280
                break;
 
281
        case MAPISTORE_MGMT_SEND:
 
282
                break;
 
283
        }
 
284
 
 
285
        return true;
 
286
}
 
287
 
 
288
static bool mapistore_mgmt_message_notification_message(struct mapistore_mgmt_users *user_cmd,
 
289
                                                        struct mapistore_mgmt_notification_cmd notif)
 
290
{
 
291
        struct mapistore_mgmt_notif     *el;
 
292
        bool                            found = true;
 
293
 
 
294
        if (!notif.MessageID) return false;
 
295
 
 
296
        switch (notif.status) {
 
297
        case MAPISTORE_MGMT_REGISTER:
 
298
                for (el = user_cmd->notifications; el; el = el->next) {
 
299
                        if ((el->MessageID == notif.MessageID) &&
 
300
                            (el->NotificationFlags == notif.NotificationFlags)) {
 
301
                                found = true;
 
302
                                el->ref_count += 1;
 
303
                                break;
 
304
                        }
 
305
                }
 
306
                if (found == false) {
 
307
                        mapistore_mgmt_message_notification_command_add(user_cmd, notif);
 
308
                }
 
309
                break;
 
310
        case MAPISTORE_MGMT_UNREGISTER:
 
311
                for (el = user_cmd->notifications; el; el = el->next) {
 
312
                        if ((el->MessageID == notif.MessageID) &&
 
313
                            (el->NotificationFlags == notif.NotificationFlags)) {
 
314
                                el->ref_count -= 1;
 
315
                                if (!el->ref_count) {
 
316
                                        DEBUG(0, ("[%s:%d]: Deleting Message subscription\n", 
 
317
                                                  __FUNCTION__, __LINE__));
 
318
                                        DLIST_REMOVE(user_cmd->notifications, el);
 
319
                                        talloc_free(el);
 
320
                                        return true;
 
321
                                }
 
322
                        }
 
323
                }
 
324
                DEBUG(0, ("[%s:%d]: Unregistered subscription found\n", __FUNCTION__, __LINE__));
 
325
                break;
 
326
        case MAPISTORE_MGMT_SEND:
 
327
                break;
 
328
        }
 
329
 
 
330
        return true;
 
331
}
 
332
 
 
333
static bool mapistore_mgmt_message_notification_folder(struct mapistore_mgmt_users *user_cmd,
 
334
                                                       struct mapistore_mgmt_notification_cmd notif)
 
335
{
 
336
        struct mapistore_mgmt_notif     *el;
 
337
        bool                            found = true;
 
338
 
 
339
        if (!notif.FolderID) return false;
 
340
 
 
341
        switch (notif.status) {
 
342
        case MAPISTORE_MGMT_REGISTER:
 
343
                for (el = user_cmd->notifications; el; el = el->next) {
 
344
                        if (!el->MessageID && (el->FolderID == notif.FolderID) &&
 
345
                            (el->NotificationFlags == notif.NotificationFlags)) {
 
346
                                found = true;
 
347
                                el->ref_count += 1;
 
348
                                break;
 
349
                        }
 
350
                }
 
351
                if (found == false) {
 
352
                        mapistore_mgmt_message_notification_command_add(user_cmd, notif);
 
353
                }
 
354
                break;
 
355
        case MAPISTORE_MGMT_UNREGISTER:
 
356
                for (el = user_cmd->notifications; el; el = el->next) {
 
357
                        if (!el->MessageID && (el->FolderID == notif.FolderID) &&
 
358
                            (el->NotificationFlags == notif.NotificationFlags)) {
 
359
                                el->ref_count -= 1;
 
360
                                if (!el->ref_count) {
 
361
                                        DEBUG(0, ("[%s:%d]: Deleting Folder subscription\n", 
 
362
                                                  __FUNCTION__, __LINE__));
 
363
                                        DLIST_REMOVE(user_cmd->notifications, el);
 
364
                                        talloc_free(el);
 
365
                                        return true;
 
366
                                }
 
367
                        }
 
368
                }
 
369
                DEBUG(0, ("[%s:%d]: Unregistered subscription found\n", __FUNCTION__, __LINE__));
 
370
                break;
 
371
        case MAPISTORE_MGMT_SEND:
 
372
                break;
 
373
        }
 
374
 
 
375
        return true;
 
376
}
 
377
 
 
378
enum mapistore_error mapistore_mgmt_message_notification_command(struct mapistore_mgmt_context *mgmt_ctx,
 
379
                                                                 struct mapistore_mgmt_notification_cmd notif)
 
380
{
 
381
        struct mapistore_mgmt_users     *el;
 
382
        bool                            ret;
 
383
 
 
384
 
 
385
        /* Sanity checks */
 
386
        MAPISTORE_RETVAL_IF(!mgmt_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
 
387
        MAPISTORE_RETVAL_IF(!mgmt_ctx->users, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
 
388
        MAPISTORE_RETVAL_IF(!notif.username || (!notif.MAPIStoreURI && notif.WholeStore == false) || 
 
389
                            (!notif.FolderID && notif.WholeStore == false), MAPI_E_INVALID_PARAMETER, NULL);
 
390
 
 
391
        for (el = mgmt_ctx->users; el; el = el->next) {
 
392
                if (!strcmp(el->info->username, notif.username)) {
 
393
                        /* Case where no notifications has been registered yet */
 
394
                        if (el->notifications == NULL) {
 
395
                                mapistore_mgmt_message_notification_command_add(el, notif);
 
396
                        } else {
 
397
                                /* subscription on wholestore case */
 
398
                                ret = mapistore_mgmt_message_notification_wholestore(el, notif);
 
399
                                if (ret == false) {
 
400
                                        /* subscription on message case */
 
401
                                        ret = mapistore_mgmt_message_notification_message(el, notif);
 
402
                                        if (ret == false) {
 
403
                                                /* subscription on folder case */
 
404
                                                ret = mapistore_mgmt_message_notification_folder(el, notif);
 
405
                                        }
 
406
                                }
 
407
                        }
 
408
                }
 
409
        }
 
410
        
 
411
        return MAPISTORE_SUCCESS;
 
412
}