2
OpenChange Storage Abstraction Layer library
6
Copyright (C) Julien Kerihuel 2011
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.
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.
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/>.
23
\file mapistore_mgmt_messages.c
25
\brief Process IPC messages received on command message queue.
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"
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,
38
struct mapistore_mgmt_users *el;
40
el = talloc_zero((TALLOC_CTX *)mgmt_ctx, struct mapistore_mgmt_users);
42
DEBUG(0, ("[%s:%d]: Not enough memory\n", __FUNCTION__, __LINE__));
43
return MAPISTORE_ERR_NO_MEMORY;
45
el->info = talloc_zero((TALLOC_CTX *)el, struct mapistore_mgmt_user_cmd);
48
DEBUG(0, ("[%s:%d]: Not enough memory\n", __FUNCTION__, __LINE__));
49
return MAPISTORE_ERR_NO_MEMORY;
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);
55
el->info->backend = NULL;
56
el->info->vuser = NULL;
58
el->info->username = talloc_strdup((TALLOC_CTX *)el->info, user_cmd.username);
60
el->notify_ctx = NULL;
62
DLIST_ADD_END(mgmt_ctx->users, el, struct mapistore_mgmt_users);
64
return MAPISTORE_SUCCESS;
67
enum mapistore_error mapistore_mgmt_message_user_command(struct mapistore_mgmt_context *mgmt_ctx,
68
struct mapistore_mgmt_user_cmd user_cmd)
70
struct mapistore_mgmt_users *el;
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);
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);
82
DEBUG(0, ("[%s:%d]: Trying to unregister user %s in empty list\n",
83
__FUNCTION__, __LINE__, user_cmd.username));
84
return MAPISTORE_SUCCESS;
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) {
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);
98
case MAPISTORE_MGMT_UNREGISTER:
100
/* Delete record if ref_count is 0 */
101
if (el->ref_count == 0) {
102
DLIST_REMOVE(mgmt_ctx->users, el);
107
case MAPISTORE_MGMT_SEND:
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))) {
116
switch (user_cmd.status) {
117
case MAPISTORE_MGMT_REGISTER:
120
case MAPISTORE_MGMT_UNREGISTER:
122
/* Delete record if ref_count is 0 */
123
if (el->ref_count == 0) {
124
DLIST_REMOVE(mgmt_ctx->users, el);
130
DEBUG(0, ("[%s:%d]: Invalid user command status: %d\n",
131
__FUNCTION__, __LINE__, user_cmd.status));
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);
142
case MAPISTORE_MGMT_UNREGISTER:
143
DEBUG(0, ("[%s:%d]: Trying to unregister non-existing users %s\n",
144
__FUNCTION__, __LINE__, user_cmd.username));
147
DEBUG(0, ("[%s:%d]: Invalid user command status: %d\n",
148
__FUNCTION__, __LINE__, user_cmd.status));
154
return MAPISTORE_SUCCESS;
157
enum mapistore_error mapistore_mgmt_message_bind_command(struct mapistore_mgmt_context *mgmt_ctx,
158
struct mapistore_mgmt_bind_cmd bind)
160
struct mapistore_mgmt_users *el;
162
struct mapistore_mgmt_user_cmd user_cmd;
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);
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);
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);
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);
190
/* socket / connect calls */
192
el->notify_ctx->fd = socket(PF_INET, SOCK_DGRAM|SOCK_NONBLOCK, IPPROTO_UDP);
193
#else /* SOCK_NONBLOCK */
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);
200
#endif /* SOCK_NONBLOCK */
202
if (el->notify_ctx->fd == -1) {
204
talloc_free(el->notify_ctx);
207
if (connect(el->notify_ctx->fd, el->notify_ctx->addr, sizeof (struct sockaddr)) == -1) {
209
talloc_free(el->notify_ctx);
216
return (found == true) ? MAPISTORE_SUCCESS : MAPISTORE_ERR_NOT_FOUND;
219
static enum mapistore_error mapistore_mgmt_message_notification_command_add(struct mapistore_mgmt_users *user_cmd,
220
struct mapistore_mgmt_notification_cmd notif)
222
struct mapistore_mgmt_notif *el;
224
el = talloc_zero((TALLOC_CTX *)user_cmd, struct mapistore_mgmt_notif);
226
DEBUG(0, ("[%s:%d]: Not enough memory\n", __FUNCTION__, __LINE__));
227
return MAPISTORE_ERR_NO_MEMORY;
229
el->WholeStore = notif.WholeStore;
230
el->NotificationFlags = notif.NotificationFlags;
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;
238
DLIST_ADD_END(user_cmd->notifications, el, struct mapistore_mgmt_notif);
240
return MAPISTORE_SUCCESS;
243
static bool mapistore_mgmt_message_notification_wholestore(struct mapistore_mgmt_users *user_cmd,
244
struct mapistore_mgmt_notification_cmd notif)
246
struct mapistore_mgmt_notif *el;
249
if (notif.WholeStore == false) return false;
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)) {
261
if (found == false) {
262
mapistore_mgmt_message_notification_command_add(user_cmd, notif);
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)) {
270
if (!el->ref_count) {
271
DEBUG(0, ("[%s:%d]: Deleting WholeStore subscription\n",
272
__FUNCTION__, __LINE__));
273
DLIST_REMOVE(user_cmd->notifications, el);
279
DEBUG(0, ("[%s:%d]: Unregistered subscription found\n", __FUNCTION__, __LINE__));
281
case MAPISTORE_MGMT_SEND:
288
static bool mapistore_mgmt_message_notification_message(struct mapistore_mgmt_users *user_cmd,
289
struct mapistore_mgmt_notification_cmd notif)
291
struct mapistore_mgmt_notif *el;
294
if (!notif.MessageID) return false;
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)) {
306
if (found == false) {
307
mapistore_mgmt_message_notification_command_add(user_cmd, notif);
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)) {
315
if (!el->ref_count) {
316
DEBUG(0, ("[%s:%d]: Deleting Message subscription\n",
317
__FUNCTION__, __LINE__));
318
DLIST_REMOVE(user_cmd->notifications, el);
324
DEBUG(0, ("[%s:%d]: Unregistered subscription found\n", __FUNCTION__, __LINE__));
326
case MAPISTORE_MGMT_SEND:
333
static bool mapistore_mgmt_message_notification_folder(struct mapistore_mgmt_users *user_cmd,
334
struct mapistore_mgmt_notification_cmd notif)
336
struct mapistore_mgmt_notif *el;
339
if (!notif.FolderID) return false;
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)) {
351
if (found == false) {
352
mapistore_mgmt_message_notification_command_add(user_cmd, notif);
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)) {
360
if (!el->ref_count) {
361
DEBUG(0, ("[%s:%d]: Deleting Folder subscription\n",
362
__FUNCTION__, __LINE__));
363
DLIST_REMOVE(user_cmd->notifications, el);
369
DEBUG(0, ("[%s:%d]: Unregistered subscription found\n", __FUNCTION__, __LINE__));
371
case MAPISTORE_MGMT_SEND:
378
enum mapistore_error mapistore_mgmt_message_notification_command(struct mapistore_mgmt_context *mgmt_ctx,
379
struct mapistore_mgmt_notification_cmd notif)
381
struct mapistore_mgmt_users *el;
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);
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);
397
/* subscription on wholestore case */
398
ret = mapistore_mgmt_message_notification_wholestore(el, notif);
400
/* subscription on message case */
401
ret = mapistore_mgmt_message_notification_message(el, notif);
403
/* subscription on folder case */
404
ret = mapistore_mgmt_message_notification_folder(el, notif);
411
return MAPISTORE_SUCCESS;