summaryrefslogtreecommitdiff
path: root/src/fdevent_select.c
blob: fe9d7236ed5f911e320629d1696de4a530f389a9 (plain)
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
#include <sys/time.h>
#include <sys/types.h>

#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>

#include "fdevent.h"
#include "settings.h"
#include "buffer.h"

#ifdef USE_SELECT

static int fdevent_select_reset(fdevents *ev) {
	FD_ZERO(&(ev->select_set_read));
	FD_ZERO(&(ev->select_set_write));
	FD_ZERO(&(ev->select_set_error));
	ev->select_max_fd = -1;

	return 0;
}

static int fdevent_select_event_del(fdevents *ev, int fde_ndx, int fd) {
	if (fde_ndx < 0) return -1;

	FD_CLR(fd, &(ev->select_set_read));
	FD_CLR(fd, &(ev->select_set_write));
	FD_CLR(fd, &(ev->select_set_error));

	return -1;
}

static int fdevent_select_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
	UNUSED(fde_ndx);

	if (events & FDEVENT_IN) {
		FD_SET(fd, &(ev->select_set_read));
		FD_CLR(fd, &(ev->select_set_write));
	}
	if (events & FDEVENT_OUT) {
		FD_CLR(fd, &(ev->select_set_read));
		FD_SET(fd, &(ev->select_set_write));
	}
	FD_SET(fd, &(ev->select_set_error));
	
	if (fd > ev->select_max_fd) ev->select_max_fd = fd;
	
	return fd;
}

static int fdevent_select_poll(fdevents *ev, int timeout_ms) {
	struct timeval tv;
	
	tv.tv_sec =  timeout_ms / 1000;
	tv.tv_usec = (timeout_ms % 1000) * 1000;
	
	ev->select_read = ev->select_set_read;
	ev->select_write = ev->select_set_write;
	ev->select_error = ev->select_set_error;
	
	return select(ev->select_max_fd + 1, &(ev->select_read), &(ev->select_write), &(ev->select_error), &tv);
}

static int fdevent_select_event_get_revent(fdevents *ev, size_t ndx) {
	int revents = 0;
	
	if (FD_ISSET(ndx, &(ev->select_read))) {
		revents |= FDEVENT_IN;
	}
	if (FD_ISSET(ndx, &(ev->select_write))) {
		revents |= FDEVENT_OUT;
	}
	if (FD_ISSET(ndx, &(ev->select_error))) {
		revents |= FDEVENT_ERR;
	}
	
	return revents;
}

static int fdevent_select_event_get_fd(fdevents *ev, size_t ndx) {
	UNUSED(ev);

	return ndx;
}

static int fdevent_select_event_next_fdndx(fdevents *ev, int ndx) {
	int i;
	
	i = (ndx < 0) ? 0 : ndx + 1;
	
	for (; i < ev->select_max_fd + 1; i++) {
		if (FD_ISSET(i, &(ev->select_read))) break;
		if (FD_ISSET(i, &(ev->select_write))) break;
		if (FD_ISSET(i, &(ev->select_error))) break;
	}
	
	return i;
}

int fdevent_select_init(fdevents *ev) {
	ev->type = FDEVENT_HANDLER_SELECT;
#define SET(x) \
	ev->x = fdevent_select_##x;
	
	SET(reset);
	SET(poll);
	
	SET(event_del);
	SET(event_add);
	
	SET(event_next_fdndx);
	SET(event_get_fd);
	SET(event_get_revent);
	
	return 0;
}

#else
int fdevent_select_init(fdevents *ev) {
	UNUSED(ev);

	return -1;
}
#endif