File: getchannels.c

package info (click to toggle)
redict 7.3.6%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 15,112 kB
  • sloc: ansic: 129,434; tcl: 46,164; makefile: 930; python: 815; ruby: 572; sh: 482; javascript: 30
file content (75 lines) | stat: -rw-r--r-- 2,676 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// SPDX-FileCopyrightText: 2024 Redict Contributors
// SPDX-FileCopyrightText: 2024 Salvatore Sanfilippo <antirez at gmail dot com>
//
// SPDX-License-Identifier: BSD-3-Clause
// SPDX-License-Identifier: LGPL-3.0-only

#include "redictmodule.h"
#include <strings.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>

/* A sample with declarable channels, that are used to validate against ACLs */
int getChannels_subscribe(RedictModuleCtx *ctx, RedictModuleString **argv, int argc) {
    if ((argc - 1) % 3 != 0) {
        RedictModule_WrongArity(ctx);
        return REDICTMODULE_OK;
    }
    char *err = NULL;
    
    /* getchannels.command [[subscribe|unsubscribe|publish] [pattern|literal] <channel> ...]
     * This command marks the given channel is accessed based on the
     * provided modifiers. */
    for (int i = 1; i < argc; i += 3) {
        const char *operation = RedictModule_StringPtrLen(argv[i], NULL);
        const char *type = RedictModule_StringPtrLen(argv[i+1], NULL);
        int flags = 0;

        if (!strcasecmp(operation, "subscribe")) {
            flags |= REDICTMODULE_CMD_CHANNEL_SUBSCRIBE;
        } else if (!strcasecmp(operation, "unsubscribe")) {
            flags |= REDICTMODULE_CMD_CHANNEL_UNSUBSCRIBE;
        } else if (!strcasecmp(operation, "publish")) {
            flags |= REDICTMODULE_CMD_CHANNEL_PUBLISH;
        } else {
            err = "Invalid channel operation";
            break;
        }

        if (!strcasecmp(type, "literal")) {
            /* No op */
        } else if (!strcasecmp(type, "pattern")) {
            flags |= REDICTMODULE_CMD_CHANNEL_PATTERN;
        } else {
            err = "Invalid channel type";
            break;
        }
        if (RedictModule_IsChannelsPositionRequest(ctx)) {
            RedictModule_ChannelAtPosWithFlags(ctx, i+2, flags);
        }
    }

    if (!RedictModule_IsChannelsPositionRequest(ctx)) {
        if (err) {
            RedictModule_ReplyWithError(ctx, err);
        } else {
            /* Normal implementation would go here, but for tests just return okay */
            RedictModule_ReplyWithSimpleString(ctx, "OK");
        }
    }

    return REDICTMODULE_OK;
}

int RedictModule_OnLoad(RedictModuleCtx *ctx, RedictModuleString **argv, int argc) {
    REDICTMODULE_NOT_USED(argv);
    REDICTMODULE_NOT_USED(argc);
    if (RedictModule_Init(ctx, "getchannels", 1, REDICTMODULE_APIVER_1) == REDICTMODULE_ERR)
        return REDICTMODULE_ERR;

    if (RedictModule_CreateCommand(ctx, "getchannels.command", getChannels_subscribe, "getchannels-api", 0, 0, 0) == REDICTMODULE_ERR)
        return REDICTMODULE_ERR;

    return REDICTMODULE_OK;
}