demux.c 5.25 KB
Newer Older
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/* -*- Mode: C; c-basic-offset:4 ; -*- */
/*
 *  (C) 2008 by Argonne National Laboratory.
 *      See COPYRIGHT in top-level directory.
 */

#include "demux.h"
#include "demux_internal.h"

int HYDT_dmxu_num_cb_fds = 0;
struct HYDT_dmxu_callback *HYDT_dmxu_cb_list = NULL;
struct HYDT_dmxu_fns HYDT_dmxu_fns = { 0 };

HYD_status HYDT_dmx_init(char **demux)
{
    HYD_status status = HYD_SUCCESS;

    HYDU_FUNC_ENTER();

    if (!(*demux)) { /* user didn't specify anything */
#if defined HAVE_POLL
        HYDT_dmxu_fns.wait_for_event = HYDT_dmxu_poll_wait_for_event;
        HYDT_dmxu_fns.stdin_valid = HYDT_dmxu_poll_stdin_valid;
        *demux = HYDU_strdup("poll");
#elif defined HAVE_SELECT
        HYDT_dmxu_fns.wait_for_event = HYDT_dmxu_select_wait_for_event;
        HYDT_dmxu_fns.stdin_valid = HYDT_dmxu_select_stdin_valid;
        *demux = HYDU_strdup("select");
#endif /* HAVE_SELECT */
    }
    else if (!strcmp(*demux, "poll")) { /* user wants to use poll */
#if defined HAVE_POLL
        HYDT_dmxu_fns.wait_for_event = HYDT_dmxu_poll_wait_for_event;
        HYDT_dmxu_fns.stdin_valid = HYDT_dmxu_poll_stdin_valid;
#endif /* HAVE_POLL */
    }
    else if (!strcmp(*demux, "select")) { /* user wants to use select */
#if defined HAVE_SELECT
        HYDT_dmxu_fns.wait_for_event = HYDT_dmxu_select_wait_for_event;
        HYDT_dmxu_fns.stdin_valid = HYDT_dmxu_select_stdin_valid;
#endif /* HAVE_SELECT */
    }

    if (HYDT_dmxu_fns.wait_for_event == NULL || HYDT_dmxu_fns.stdin_valid == NULL) {
        /* We couldn't find anything; return an error */
        HYDU_ERR_SETANDJUMP(status, HYD_INTERNAL_ERROR, "cannot find an appropriate demux engine\n");
    }

  fn_exit:
    HYDU_FUNC_EXIT();
    return status;

  fn_fail:
    goto fn_exit;
}

HYD_status HYDT_dmx_register_fd(int num_fds, int *fd, HYD_event_t events, void *userp,
                                HYD_status(*callback) (int fd, HYD_event_t events,
                                                       void *userp))
{
    struct HYDT_dmxu_callback *cb_element, *run;
#if defined HAVE_ERROR_CHECKING
    int i, j;
#endif /* HAVE_ERROR_CHECKING */
    HYD_status status = HYD_SUCCESS;

    HYDU_FUNC_ENTER();

    HYDU_ASSERT(events, status);

#if defined HAVE_ERROR_CHECKING
    for (i = 0; i < num_fds; i++) {
        if (fd[i] < 0)
            HYDU_ERR_SETANDJUMP1(status, HYD_INTERNAL_ERROR, "registering bad fd %d\n", fd[i]);

        cb_element = HYDT_dmxu_cb_list;
        while (cb_element) {
            for (j = 0; j < cb_element->num_fds; j++) {
                if (cb_element->fd[j] == fd[i]) {
                    HYDU_ERR_SETANDJUMP1(status, HYD_INTERNAL_ERROR,
                                         "registering duplicate fd %d\n", fd[i]);
                }
            }
            cb_element = cb_element->next;
        }
    }
#endif /* HAVE_ERROR_CHECKING */

    HYDU_MALLOC(cb_element, struct HYDT_dmxu_callback *, sizeof(struct HYDT_dmxu_callback), status);
    cb_element->num_fds = num_fds;
    HYDU_MALLOC(cb_element->fd, int *, num_fds * sizeof(int), status);
    memcpy(cb_element->fd, fd, num_fds * sizeof(int));
    cb_element->events = events;
    cb_element->userp = userp;
    cb_element->callback = callback;
    cb_element->next = NULL;

    if (HYDT_dmxu_cb_list == NULL) {
        HYDT_dmxu_cb_list = cb_element;
    }
    else {
        run = HYDT_dmxu_cb_list;
        while (run->next)
            run = run->next;
        run->next = cb_element;
    }

    HYDT_dmxu_num_cb_fds += num_fds;

  fn_exit:
    HYDU_FUNC_EXIT();
    return status;

  fn_fail:
    goto fn_exit;
}

HYD_status HYDT_dmx_deregister_fd(int fd)
{
    int i;
    struct HYDT_dmxu_callback *cb_element;
    HYD_status status = HYD_SUCCESS;

    HYDU_FUNC_ENTER();

    cb_element = HYDT_dmxu_cb_list;
    while (cb_element) {
        for (i = 0; i < cb_element->num_fds; i++) {
            if (cb_element->fd[i] == fd) {
                cb_element->fd[i] = -1;
                HYDT_dmxu_num_cb_fds--;
                goto fn_exit;
            }
        }
        cb_element = cb_element->next;
    }

    /* FD is not found */
    HYDU_ERR_SETANDJUMP1(status, HYD_INTERNAL_ERROR,
                         "could not find fd to deregister: %d\n", fd);

  fn_exit:
    HYDU_FUNC_EXIT();
    return status;

  fn_fail:
    goto fn_exit;
}

HYD_status HYDT_dmx_wait_for_event(int wtime)
{
    return HYDT_dmxu_fns.wait_for_event(wtime);
}

Pavan Balaji's avatar
Pavan Balaji committed
155
int HYDT_dmx_query_fd_registration(int fd)
156
157
{
    struct HYDT_dmxu_callback *run;
Pavan Balaji's avatar
Pavan Balaji committed
158
    int i, ret;
159
160
161

    HYDU_FUNC_ENTER();

Pavan Balaji's avatar
Pavan Balaji committed
162
    ret = 0;
163
164
165
    for (run = HYDT_dmxu_cb_list; run; run = run->next) {
        for (i = 0; i < run->num_fds; i++) {
            if (run->fd[i] == fd) {     /* found it */
Pavan Balaji's avatar
Pavan Balaji committed
166
                ret = 1;
167
168
169
                break;
            }
        }
Pavan Balaji's avatar
Pavan Balaji committed
170
        if (ret)
171
172
173
174
175
            break;
    }

    HYDU_FUNC_EXIT();

Pavan Balaji's avatar
Pavan Balaji committed
176
    return ret;
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
}

HYD_status HYDT_dmx_finalize(void)
{
    struct HYDT_dmxu_callback *run1, *run2;
    HYD_status status = HYD_SUCCESS;

    HYDU_FUNC_ENTER();

    run1 = HYDT_dmxu_cb_list;
    while (run1) {
        run2 = run1->next;
        if (run1->fd)
            HYDU_FREE(run1->fd);
        HYDU_FREE(run1);
        run1 = run2;
    }
    HYDT_dmxu_cb_list = NULL;

    HYDU_FUNC_EXIT();
    return status;
}

HYD_status HYDT_dmx_stdin_valid(int *out)
{
    return HYDT_dmxu_fns.stdin_valid(out);
}