Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/util/verto/verto.c
34907 views
1
/*
2
* Copyright 2011 Red Hat, Inc.
3
*
4
* Permission is hereby granted, free of charge, to any person
5
* obtaining a copy of this software and associated documentation files
6
* (the "Software"), to deal in the Software without restriction,
7
* including without limitation the rights to use, copy, modify, merge,
8
* publish, distribute, sublicense, and/or sell copies of the Software,
9
* and to permit persons to whom the Software is furnished to do so,
10
* subject to the following conditions:
11
*
12
* The above copyright notice and this permission notice shall be
13
* included in all copies or substantial portions of the Software.
14
*
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
* SOFTWARE.
23
*/
24
25
#include <stdio.h>
26
#include <stdlib.h>
27
#include <string.h>
28
#include <signal.h>
29
#include <assert.h>
30
#include <stdarg.h>
31
32
#include <libgen.h>
33
#include <sys/types.h>
34
#include <dirent.h>
35
36
#ifdef HAVE_PTHREAD
37
#include <pthread.h>
38
#endif
39
40
#include <verto-module.h>
41
#include "module.h"
42
43
#define _str(s) # s
44
#define __str(s) _str(s)
45
46
#define MUTABLE(flags) (flags & _VERTO_EV_FLAG_MUTABLE_MASK)
47
48
/* Remove flags we can emulate */
49
#define make_actual(flags) ((flags) & ~(VERTO_EV_FLAG_PERSIST|VERTO_EV_FLAG_IO_CLOSE_FD))
50
51
struct verto_ctx {
52
size_t ref;
53
verto_mod_ctx *ctx;
54
const verto_module *module;
55
verto_ev *events;
56
int deflt;
57
int exit;
58
};
59
60
typedef struct {
61
verto_proc proc;
62
verto_proc_status status;
63
} verto_child;
64
65
typedef struct {
66
int fd;
67
verto_ev_flag state;
68
} verto_io;
69
70
struct verto_ev {
71
verto_ev *next;
72
verto_ctx *ctx;
73
verto_ev_type type;
74
verto_callback *callback;
75
verto_callback *onfree;
76
void *priv;
77
verto_mod_ev *ev;
78
verto_ev_flag flags;
79
verto_ev_flag actual;
80
size_t depth;
81
int deleted;
82
union {
83
verto_io io;
84
int signal;
85
time_t interval;
86
verto_child child;
87
} option;
88
};
89
90
typedef struct module_record module_record;
91
struct module_record {
92
module_record *next;
93
const verto_module *module;
94
void *dll;
95
char *filename;
96
verto_ctx *defctx;
97
};
98
99
100
#ifdef BUILTIN_MODULE
101
#define _MODTABLE(n) verto_module_table_ ## n
102
#define MODTABLE(n) _MODTABLE(n)
103
/*
104
* This symbol can be used when embedding verto.c in a library along with a
105
* built-in private module, to preload the module instead of dynamically
106
* linking it in later. Define to <modulename>.
107
*/
108
extern verto_module MODTABLE(BUILTIN_MODULE);
109
static module_record builtin_record = {
110
NULL, &MODTABLE(BUILTIN_MODULE), NULL, "", NULL
111
};
112
static module_record *loaded_modules = &builtin_record;
113
#else
114
static module_record *loaded_modules;
115
#endif
116
117
static void *(*resize_cb)(void *mem, size_t size);
118
static int resize_cb_hierarchical;
119
120
#ifdef HAVE_PTHREAD
121
static pthread_mutex_t loaded_modules_mutex = PTHREAD_MUTEX_INITIALIZER;
122
123
#ifndef NDEBUG
124
#define mutex_lock(x) { \
125
int c = pthread_mutex_lock(x); \
126
if (c != 0) { \
127
fprintf(stderr, "pthread_mutex_lock returned %d (%s) in %s", \
128
c, strerror(c), __FUNCTION__); \
129
} \
130
assert(c == 0); \
131
}
132
#define mutex_unlock(x) { \
133
int c = pthread_mutex_unlock(x); \
134
if (c != 0) { \
135
fprintf(stderr, "pthread_mutex_unlock returned %d (%s) in %s", \
136
c, strerror(c), __FUNCTION__); \
137
} \
138
assert(c == 0); \
139
}
140
#define mutex_destroy(x) { \
141
int c = pthread_mutex_destroy(x); \
142
if (c != 0) { \
143
fprintf(stderr, "pthread_mutex_destroy returned %d (%s) in %s", \
144
c, strerror(c), __FUNCTION__); \
145
} \
146
assert(c == 0); \
147
}
148
#else /* NDEBUG */
149
#define mutex_lock pthread_mutex_lock
150
#define mutex_unlock pthread_mutex_unlock
151
#define mutex_destroy pthread_mutex_destroy
152
#endif /* NDEBUG */
153
154
#else /* HAVE_PTHREAD */
155
#define mutex_lock(x)
156
#define mutex_unlock(x)
157
#define mutex_destroy(x)
158
#endif /* HAVE_PTHREAD */
159
160
#define vfree(mem) vresize(mem, 0)
161
static void *
162
vresize(void *mem, size_t size)
163
{
164
if (!resize_cb)
165
resize_cb = &realloc;
166
if (size == 0 && resize_cb == &realloc) {
167
/* Avoid memleak as realloc(X, 0) can return a free-able pointer. */
168
free(mem);
169
return NULL;
170
}
171
return (*resize_cb)(mem, size);
172
}
173
174
#ifndef BUILTIN_MODULE
175
static char *
176
string_aconcat(const char *first, const char *second, const char *third) {
177
char *ret;
178
size_t len;
179
180
len = strlen(first) + strlen(second);
181
if (third)
182
len += strlen(third);
183
184
ret = malloc(len + 1);
185
if (!ret)
186
return NULL;
187
188
strncpy(ret, first, strlen(first));
189
strncpy(ret + strlen(first), second, strlen(second));
190
if (third)
191
strncpy(ret + strlen(first) + strlen(second), third, strlen(third));
192
193
ret[len] = '\0';
194
return ret;
195
}
196
197
static char *
198
int_get_table_name_from_filename(const char *filename)
199
{
200
char *bn = NULL, *tmp = NULL;
201
202
if (!filename)
203
return NULL;
204
205
tmp = strdup(filename);
206
if (!tmp)
207
return NULL;
208
209
bn = basename(tmp);
210
if (bn)
211
bn = strdup(bn);
212
free(tmp);
213
if (!bn)
214
return NULL;
215
216
tmp = strchr(bn, '-');
217
if (tmp) {
218
if (strchr(tmp+1, '.')) {
219
*strchr(tmp+1, '.') = '\0';
220
tmp = string_aconcat(__str(VERTO_MODULE_TABLE()), tmp + 1, NULL);
221
} else
222
tmp = NULL;
223
}
224
225
free(bn);
226
return tmp;
227
}
228
229
typedef struct {
230
int reqsym;
231
verto_ev_type reqtypes;
232
} shouldload_data;
233
234
static int
235
shouldload(void *symb, void *misc, char **err)
236
{
237
verto_module *table = (verto_module*) symb;
238
shouldload_data *data = (shouldload_data*) misc;
239
240
/* Make sure we have the proper version */
241
if (table->vers != VERTO_MODULE_VERSION) {
242
if (err)
243
*err = strdup("Invalid module version!");
244
return 0;
245
}
246
247
/* Check to make sure that we have our required symbol if reqsym == true */
248
if (table->symb && data->reqsym
249
&& !module_symbol_is_present(NULL, table->symb)) {
250
if (err)
251
*err = string_aconcat("Symbol not found: ", table->symb, "!");
252
return 0;
253
}
254
255
/* Check to make sure that this module supports our required features */
256
if (data->reqtypes != VERTO_EV_TYPE_NONE
257
&& (table->types & data->reqtypes) != data->reqtypes) {
258
if (err)
259
*err = strdup("Module does not support required features!");
260
return 0;
261
}
262
263
return 1;
264
}
265
266
static int
267
do_load_file(const char *filename, int reqsym, verto_ev_type reqtypes,
268
module_record **record)
269
{
270
char *tblname = NULL, *error = NULL;
271
module_record *tmp;
272
shouldload_data data = { reqsym, reqtypes };
273
274
/* Check the loaded modules to see if we already loaded one */
275
mutex_lock(&loaded_modules_mutex);
276
for (*record = loaded_modules ; *record ; *record = (*record)->next) {
277
if (!strcmp((*record)->filename, filename)) {
278
mutex_unlock(&loaded_modules_mutex);
279
return 1;
280
}
281
}
282
mutex_unlock(&loaded_modules_mutex);
283
284
/* Create our module record */
285
tmp = *record = vresize(NULL, sizeof(module_record));
286
if (!tmp)
287
return 0;
288
memset(tmp, 0, sizeof(module_record));
289
tmp->filename = strdup(filename);
290
if (!tmp->filename) {
291
vfree(tmp);
292
return 0;
293
}
294
295
/* Get the name of the module struct in the library */
296
tblname = int_get_table_name_from_filename(filename);
297
if (!tblname) {
298
free(tblname);
299
free(tmp->filename);
300
vfree(tmp);
301
return 0;
302
}
303
304
/* Load the module */
305
error = module_load(filename, tblname, shouldload, &data, &tmp->dll,
306
(void **) &tmp->module);
307
if (error || !tmp->dll || !tmp->module) {
308
/*if (error)
309
fprintf(stderr, "%s\n", error);*/
310
free(error);
311
module_close(tmp->dll);
312
free(tblname);
313
free(tmp->filename);
314
vfree(tmp);
315
return 0;
316
}
317
318
/* Append the new module to the end of the loaded modules */
319
mutex_lock(&loaded_modules_mutex);
320
for (tmp = loaded_modules ; tmp && tmp->next; tmp = tmp->next)
321
continue;
322
if (tmp)
323
tmp->next = *record;
324
else
325
loaded_modules = *record;
326
mutex_unlock(&loaded_modules_mutex);
327
328
free(tblname);
329
return 1;
330
}
331
332
static int
333
do_load_dir(const char *dirname, const char *prefix, const char *suffix,
334
int reqsym, verto_ev_type reqtypes, module_record **record)
335
{
336
DIR *dir;
337
struct dirent *ent = NULL;
338
339
*record = NULL;
340
dir = opendir(dirname);
341
if (!dir)
342
return 0;
343
344
345
while ((ent = readdir(dir))) {
346
char *tmp = NULL;
347
int success;
348
size_t flen, slen;
349
350
flen = strlen(ent->d_name);
351
slen = strlen(suffix);
352
353
if (!strcmp(".", ent->d_name) || !strcmp("..", ent->d_name))
354
continue;
355
if (strstr(ent->d_name, prefix) != ent->d_name)
356
continue;
357
if (flen < slen || strcmp(ent->d_name + flen - slen, suffix))
358
continue;
359
360
tmp = string_aconcat(dirname, "/", ent->d_name);
361
if (!tmp)
362
continue;
363
364
success = do_load_file(tmp, reqsym, reqtypes, record);
365
free(tmp);
366
if (success)
367
break;
368
*record = NULL;
369
}
370
371
closedir(dir);
372
return *record != NULL;
373
}
374
#endif
375
376
static int
377
load_module(const char *impl, verto_ev_type reqtypes, module_record **record)
378
{
379
int success = 0;
380
#ifndef BUILTIN_MODULE
381
char *prefix = NULL;
382
char *suffix = NULL;
383
char *tmp = NULL;
384
#endif
385
386
/* Check the cache */
387
mutex_lock(&loaded_modules_mutex);
388
if (impl) {
389
for (*record = loaded_modules ; *record ; *record = (*record)->next) {
390
if ((strchr(impl, '/') && !strcmp(impl, (*record)->filename))
391
|| !strcmp(impl, (*record)->module->name)) {
392
mutex_unlock(&loaded_modules_mutex);
393
return 1;
394
}
395
}
396
} else if (loaded_modules) {
397
for (*record = loaded_modules ; *record ; *record = (*record)->next) {
398
if (reqtypes == VERTO_EV_TYPE_NONE
399
|| ((*record)->module->types & reqtypes) == reqtypes) {
400
mutex_unlock(&loaded_modules_mutex);
401
return 1;
402
}
403
}
404
}
405
mutex_unlock(&loaded_modules_mutex);
406
407
#ifndef BUILTIN_MODULE
408
if (!module_get_filename_for_symbol(verto_convert_module, &prefix))
409
return 0;
410
411
/* Example output:
412
* prefix == /usr/lib/libverto-
413
* impl == glib
414
* suffix == .so.0
415
* Put them all together: /usr/lib/libverto-glib.so.0 */
416
tmp = strdup(prefix);
417
if (!tmp) {
418
free(prefix);
419
return 0;
420
}
421
422
suffix = basename(tmp);
423
suffix = strchr(suffix, '.');
424
if (!suffix || strlen(suffix) < 1 || !(suffix = strdup(suffix))) {
425
free(prefix);
426
free(tmp);
427
return 0;
428
}
429
strcpy(prefix + strlen(prefix) - strlen(suffix), "-");
430
free(tmp);
431
432
if (impl) {
433
/* Try to do a load by the path */
434
if (!success && strchr(impl, '/'))
435
success = do_load_file(impl, 0, reqtypes, record);
436
if (!success) {
437
/* Try to do a load by the name */
438
tmp = string_aconcat(prefix, impl, suffix);
439
if (tmp) {
440
success = do_load_file(tmp, 0, reqtypes, record);
441
free(tmp);
442
}
443
}
444
} else {
445
/* NULL was passed, so we will use the dirname of
446
* the prefix to try and find any possible plugins */
447
tmp = strdup(prefix);
448
if (tmp) {
449
char *dname = strdup(dirname(tmp));
450
free(tmp);
451
452
tmp = strdup(basename(prefix));
453
free(prefix);
454
prefix = tmp;
455
456
if (dname && prefix) {
457
/* Attempt to find a module we are already linked to */
458
success = do_load_dir(dname, prefix, suffix, 1, reqtypes,
459
record);
460
if (!success) {
461
#ifdef DEFAULT_MODULE
462
/* Attempt to find the default module */
463
success = load_module(DEFAULT_MODULE, reqtypes, record);
464
if (!success)
465
#endif /* DEFAULT_MODULE */
466
/* Attempt to load any plugin (we're desperate) */
467
success = do_load_dir(dname, prefix, suffix, 0,
468
reqtypes, record);
469
}
470
}
471
472
free(dname);
473
}
474
}
475
476
free(suffix);
477
free(prefix);
478
#endif /* BUILTIN_MODULE */
479
return success;
480
}
481
482
static verto_ev *
483
make_ev(verto_ctx *ctx, verto_callback *callback,
484
verto_ev_type type, verto_ev_flag flags)
485
{
486
verto_ev *ev = NULL;
487
488
if (!ctx || !callback)
489
return NULL;
490
491
ev = vresize(NULL, sizeof(verto_ev));
492
if (ev) {
493
memset(ev, 0, sizeof(verto_ev));
494
ev->ctx = ctx;
495
ev->type = type;
496
ev->callback = callback;
497
ev->flags = flags;
498
}
499
500
return ev;
501
}
502
503
static void
504
push_ev(verto_ctx *ctx, verto_ev *ev)
505
{
506
verto_ev *tmp;
507
508
if (!ctx || !ev)
509
return;
510
511
tmp = ctx->events;
512
ctx->events = ev;
513
ctx->events->next = tmp;
514
}
515
516
static void
517
remove_ev(verto_ev **origin, verto_ev *item)
518
{
519
if (!origin || !*origin || !item)
520
return;
521
522
if (*origin == item)
523
*origin = (*origin)->next;
524
else
525
remove_ev(&((*origin)->next), item);
526
}
527
528
static void
529
signal_ignore(verto_ctx *ctx, verto_ev *ev)
530
{
531
(void) ctx;
532
(void) ev;
533
}
534
535
verto_ctx *
536
verto_new(const char *impl, verto_ev_type reqtypes)
537
{
538
module_record *mr = NULL;
539
540
if (!load_module(impl, reqtypes, &mr))
541
return NULL;
542
543
return verto_convert_module(mr->module, 0, NULL);
544
}
545
546
verto_ctx *
547
verto_default(const char *impl, verto_ev_type reqtypes)
548
{
549
module_record *mr = NULL;
550
551
if (!load_module(impl, reqtypes, &mr))
552
return NULL;
553
554
return verto_convert_module(mr->module, 1, NULL);
555
}
556
557
int
558
verto_set_default(const char *impl, verto_ev_type reqtypes)
559
{
560
module_record *mr;
561
562
mutex_lock(&loaded_modules_mutex);
563
if (loaded_modules || !impl) {
564
mutex_unlock(&loaded_modules_mutex);
565
return 0;
566
}
567
mutex_unlock(&loaded_modules_mutex);
568
569
return load_module(impl, reqtypes, &mr);
570
}
571
572
int
573
verto_set_allocator(void *(*resize)(void *mem, size_t size),
574
int hierarchical)
575
{
576
if (resize_cb || !resize)
577
return 0;
578
resize_cb = resize;
579
resize_cb_hierarchical = hierarchical;
580
return 1;
581
}
582
583
void
584
verto_free(verto_ctx *ctx)
585
{
586
if (!ctx)
587
return;
588
589
ctx->ref = ctx->ref > 0 ? ctx->ref - 1 : 0;
590
if (ctx->ref > 0)
591
return;
592
593
/* Cancel all pending events */
594
while (ctx->events)
595
verto_del(ctx->events);
596
597
/* Free the private */
598
if (!ctx->deflt || !ctx->module->funcs->ctx_default)
599
ctx->module->funcs->ctx_free(ctx->ctx);
600
601
vfree(ctx);
602
}
603
604
void
605
verto_cleanup(void)
606
{
607
module_record *record;
608
609
mutex_lock(&loaded_modules_mutex);
610
611
for (record = loaded_modules; record; record = record->next) {
612
module_close(record->dll);
613
free(record->filename);
614
}
615
616
vfree(loaded_modules);
617
loaded_modules = NULL;
618
619
mutex_unlock(&loaded_modules_mutex);
620
mutex_destroy(&loaded_modules_mutex);
621
}
622
623
void
624
verto_run(verto_ctx *ctx)
625
{
626
if (!ctx)
627
return;
628
629
if (ctx->module->funcs->ctx_break && ctx->module->funcs->ctx_run)
630
ctx->module->funcs->ctx_run(ctx->ctx);
631
else {
632
while (!ctx->exit)
633
ctx->module->funcs->ctx_run_once(ctx->ctx);
634
ctx->exit = 0;
635
}
636
}
637
638
void
639
verto_run_once(verto_ctx *ctx)
640
{
641
if (!ctx)
642
return;
643
ctx->module->funcs->ctx_run_once(ctx->ctx);
644
}
645
646
void
647
verto_break(verto_ctx *ctx)
648
{
649
if (!ctx)
650
return;
651
652
if (ctx->module->funcs->ctx_break && ctx->module->funcs->ctx_run)
653
ctx->module->funcs->ctx_break(ctx->ctx);
654
else
655
ctx->exit = 1;
656
}
657
658
int
659
verto_reinitialize(verto_ctx *ctx)
660
{
661
verto_ev *tmp, *next;
662
int error = 1;
663
664
if (!ctx)
665
return 0;
666
667
/* Delete all events, but keep around the forkable ev structs */
668
for (tmp = ctx->events; tmp; tmp = next) {
669
next = tmp->next;
670
671
if (tmp->flags & VERTO_EV_FLAG_REINITIABLE)
672
ctx->module->funcs->ctx_del(ctx->ctx, tmp, tmp->ev);
673
else
674
verto_del(tmp);
675
}
676
677
/* Reinit the loop */
678
if (ctx->module->funcs->ctx_reinitialize)
679
ctx->module->funcs->ctx_reinitialize(ctx->ctx);
680
681
/* Recreate events that were marked forkable */
682
for (tmp = ctx->events; tmp; tmp = tmp->next) {
683
tmp->actual = make_actual(tmp->flags);
684
tmp->ev = ctx->module->funcs->ctx_add(ctx->ctx, tmp, &tmp->actual);
685
if (!tmp->ev)
686
error = 0;
687
}
688
689
return error;
690
}
691
692
#define doadd(ev, set, type) \
693
ev = make_ev(ctx, callback, type, flags); \
694
if (ev) { \
695
set; \
696
ev->actual = make_actual(ev->flags); \
697
ev->ev = ctx->module->funcs->ctx_add(ctx->ctx, ev, &ev->actual); \
698
if (!ev->ev) { \
699
vfree(ev); \
700
return NULL; \
701
} \
702
push_ev(ctx, ev); \
703
}
704
705
verto_ev *
706
verto_add_io(verto_ctx *ctx, verto_ev_flag flags,
707
verto_callback *callback, int fd)
708
{
709
verto_ev *ev;
710
711
if (fd < 0 || !(flags & (VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_IO_WRITE)))
712
return NULL;
713
714
doadd(ev, ev->option.io.fd = fd, VERTO_EV_TYPE_IO);
715
return ev;
716
}
717
718
verto_ev *
719
verto_add_timeout(verto_ctx *ctx, verto_ev_flag flags,
720
verto_callback *callback, time_t interval)
721
{
722
verto_ev *ev;
723
doadd(ev, ev->option.interval = interval, VERTO_EV_TYPE_TIMEOUT);
724
return ev;
725
}
726
727
verto_ev *
728
verto_add_idle(verto_ctx *ctx, verto_ev_flag flags,
729
verto_callback *callback)
730
{
731
verto_ev *ev;
732
doadd(ev,, VERTO_EV_TYPE_IDLE);
733
return ev;
734
}
735
736
verto_ev *
737
verto_add_signal(verto_ctx *ctx, verto_ev_flag flags,
738
verto_callback *callback, int signal)
739
{
740
verto_ev *ev;
741
742
if (signal < 0)
743
return NULL;
744
#ifndef WIN32
745
if (signal == SIGCHLD)
746
return NULL;
747
#endif
748
if (callback == VERTO_SIG_IGN) {
749
callback = signal_ignore;
750
if (!(flags & VERTO_EV_FLAG_PERSIST))
751
return NULL;
752
}
753
doadd(ev, ev->option.signal = signal, VERTO_EV_TYPE_SIGNAL);
754
return ev;
755
}
756
757
verto_ev *
758
verto_add_child(verto_ctx *ctx, verto_ev_flag flags,
759
verto_callback *callback, verto_proc proc)
760
{
761
verto_ev *ev;
762
763
if (flags & VERTO_EV_FLAG_PERSIST) /* persist makes no sense */
764
return NULL;
765
#ifdef WIN32
766
if (proc == NULL)
767
#else
768
if (proc < 1)
769
#endif
770
return NULL;
771
doadd(ev, ev->option.child.proc = proc, VERTO_EV_TYPE_CHILD);
772
return ev;
773
}
774
775
void
776
verto_set_private(verto_ev *ev, void *priv, verto_callback *free)
777
{
778
if (!ev)
779
return;
780
if (ev->onfree && free)
781
ev->onfree(ev->ctx, ev);
782
ev->priv = priv;
783
ev->onfree = free;
784
}
785
786
void *
787
verto_get_private(const verto_ev *ev)
788
{
789
return ev->priv;
790
}
791
792
verto_ev_type
793
verto_get_type(const verto_ev *ev)
794
{
795
return ev->type;
796
}
797
798
verto_ev_flag
799
verto_get_flags(const verto_ev *ev)
800
{
801
return ev->flags;
802
}
803
804
void
805
verto_set_flags(verto_ev *ev, verto_ev_flag flags)
806
{
807
if (!ev)
808
return;
809
810
/* No modification is needed, so do nothing. */
811
if (MUTABLE(ev->flags) == MUTABLE(flags))
812
return;
813
814
ev->flags &= ~_VERTO_EV_FLAG_MUTABLE_MASK;
815
ev->flags |= MUTABLE(flags);
816
817
/* If setting flags isn't supported, just rebuild the event */
818
if (!ev->ctx->module->funcs->ctx_set_flags) {
819
ev->ctx->module->funcs->ctx_del(ev->ctx->ctx, ev, ev->ev);
820
ev->actual = make_actual(ev->flags);
821
ev->ev = ev->ctx->module->funcs->ctx_add(ev->ctx->ctx, ev, &ev->actual);
822
assert(ev->ev); /* Here is the main reason why modules should */
823
return; /* implement set_flags(): we cannot fail gracefully. */
824
}
825
826
ev->actual &= ~_VERTO_EV_FLAG_MUTABLE_MASK;
827
ev->actual |= MUTABLE(flags);
828
ev->ctx->module->funcs->ctx_set_flags(ev->ctx->ctx, ev, ev->ev);
829
}
830
831
int
832
verto_get_fd(const verto_ev *ev)
833
{
834
if (ev && (ev->type == VERTO_EV_TYPE_IO))
835
return ev->option.io.fd;
836
return -1;
837
}
838
839
verto_ev_flag
840
verto_get_fd_state(const verto_ev *ev)
841
{
842
return ev->option.io.state;
843
}
844
845
time_t
846
verto_get_interval(const verto_ev *ev)
847
{
848
if (ev && (ev->type == VERTO_EV_TYPE_TIMEOUT))
849
return ev->option.interval;
850
return 0;
851
}
852
853
int
854
verto_get_signal(const verto_ev *ev)
855
{
856
if (ev && (ev->type == VERTO_EV_TYPE_SIGNAL))
857
return ev->option.signal;
858
return -1;
859
}
860
861
verto_proc
862
verto_get_proc(const verto_ev *ev) {
863
if (ev && ev->type == VERTO_EV_TYPE_CHILD)
864
return ev->option.child.proc;
865
return (verto_proc) 0;
866
}
867
868
verto_proc_status
869
verto_get_proc_status(const verto_ev *ev)
870
{
871
return ev->option.child.status;
872
}
873
874
verto_ctx *
875
verto_get_ctx(const verto_ev *ev)
876
{
877
return ev->ctx;
878
}
879
880
void
881
verto_del(verto_ev *ev)
882
{
883
if (!ev)
884
return;
885
886
/* If the event is freed in the callback, we just set a flag so that
887
* verto_fire() can actually do the delete when the callback completes.
888
*
889
* If we don't do this, than verto_fire() will access freed memory. */
890
if (ev->depth > 0) {
891
ev->deleted = 1;
892
return;
893
}
894
895
if (ev->onfree)
896
ev->onfree(ev->ctx, ev);
897
ev->ctx->module->funcs->ctx_del(ev->ctx->ctx, ev, ev->ev);
898
remove_ev(&(ev->ctx->events), ev);
899
900
if ((ev->type == VERTO_EV_TYPE_IO) &&
901
(ev->flags & VERTO_EV_FLAG_IO_CLOSE_FD) &&
902
!(ev->actual & VERTO_EV_FLAG_IO_CLOSE_FD))
903
close(ev->option.io.fd);
904
905
vfree(ev);
906
}
907
908
verto_ev_type
909
verto_get_supported_types(verto_ctx *ctx)
910
{
911
return ctx->module->types;
912
}
913
914
/*** THE FOLLOWING ARE FOR IMPLEMENTATION MODULES ONLY ***/
915
916
verto_ctx *
917
verto_convert_module(const verto_module *module, int deflt, verto_mod_ctx *mctx)
918
{
919
verto_ctx *ctx = NULL;
920
module_record *mr;
921
922
if (!module)
923
return NULL;
924
925
if (deflt) {
926
mutex_lock(&loaded_modules_mutex);
927
for (mr = loaded_modules ; mr ; mr = mr->next) {
928
verto_ctx *tmp;
929
if (mr->module == module && mr->defctx) {
930
if (mctx)
931
module->funcs->ctx_free(mctx);
932
tmp = mr->defctx;
933
tmp->ref++;
934
mutex_unlock(&loaded_modules_mutex);
935
return tmp;
936
}
937
}
938
mutex_unlock(&loaded_modules_mutex);
939
}
940
941
if (!mctx) {
942
mctx = deflt
943
? (module->funcs->ctx_default
944
? module->funcs->ctx_default()
945
: module->funcs->ctx_new())
946
: module->funcs->ctx_new();
947
if (!mctx)
948
goto error;
949
}
950
951
ctx = vresize(NULL, sizeof(verto_ctx));
952
if (!ctx)
953
goto error;
954
memset(ctx, 0, sizeof(verto_ctx));
955
956
ctx->ref = 1;
957
ctx->ctx = mctx;
958
ctx->module = module;
959
ctx->deflt = deflt;
960
961
if (deflt) {
962
module_record **tmp;
963
964
mutex_lock(&loaded_modules_mutex);
965
tmp = &loaded_modules;
966
for (mr = loaded_modules ; mr ; mr = mr->next) {
967
if (mr->module == module) {
968
assert(mr->defctx == NULL);
969
mr->defctx = ctx;
970
mutex_unlock(&loaded_modules_mutex);
971
return ctx;
972
}
973
974
if (!mr->next) {
975
tmp = &mr->next;
976
break;
977
}
978
}
979
mutex_unlock(&loaded_modules_mutex);
980
981
*tmp = vresize(NULL, sizeof(module_record));
982
if (!*tmp) {
983
vfree(ctx);
984
goto error;
985
}
986
987
memset(*tmp, 0, sizeof(module_record));
988
(*tmp)->defctx = ctx;
989
(*tmp)->module = module;
990
}
991
992
return ctx;
993
994
error:
995
if (mctx)
996
module->funcs->ctx_free(mctx);
997
return NULL;
998
}
999
1000
void
1001
verto_fire(verto_ev *ev)
1002
{
1003
void *priv;
1004
1005
ev->depth++;
1006
ev->callback(ev->ctx, ev);
1007
ev->depth--;
1008
1009
if (ev->depth == 0) {
1010
if (!(ev->flags & VERTO_EV_FLAG_PERSIST) || ev->deleted)
1011
verto_del(ev);
1012
else {
1013
if (!(ev->actual & VERTO_EV_FLAG_PERSIST)) {
1014
ev->actual = make_actual(ev->flags);
1015
priv = ev->ctx->module->funcs->ctx_add(ev->ctx->ctx, ev, &ev->actual);
1016
assert(priv); /* TODO: create an error callback */
1017
ev->ctx->module->funcs->ctx_del(ev->ctx->ctx, ev, ev->ev);
1018
ev->ev = priv;
1019
}
1020
1021
if (ev->type == VERTO_EV_TYPE_IO)
1022
ev->option.io.state = VERTO_EV_FLAG_NONE;
1023
if (ev->type == VERTO_EV_TYPE_CHILD)
1024
ev->option.child.status = 0;
1025
}
1026
}
1027
}
1028
1029
void
1030
verto_set_proc_status(verto_ev *ev, verto_proc_status status)
1031
{
1032
if (ev && ev->type == VERTO_EV_TYPE_CHILD)
1033
ev->option.child.status = status;
1034
}
1035
1036
void
1037
verto_set_fd_state(verto_ev *ev, verto_ev_flag state)
1038
{
1039
/* Filter out only the io flags */
1040
state = state & (VERTO_EV_FLAG_IO_READ |
1041
VERTO_EV_FLAG_IO_WRITE |
1042
VERTO_EV_FLAG_IO_ERROR);
1043
1044
/* Don't report read/write if the socket is closed */
1045
if (state & VERTO_EV_FLAG_IO_ERROR)
1046
state = VERTO_EV_FLAG_IO_ERROR;
1047
1048
if (ev && ev->type == VERTO_EV_TYPE_IO)
1049
ev->option.io.state = state;
1050
}
1051
1052