added IRC Client and RAW pass-through
[TransparentIRC.git] / src / IOEngine_select.c
1 /* IOEngine_select.c - TransparentIRC 0.1
2  * Copyright (C) 2011-2012  Philipp Kreil (pk910)
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License 
15  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
16  */
17 #include "IOEngine.h"
18 #include "IOHandler.h"
19
20 static int engine_select_init() {
21     /* empty */
22     return 1;
23 }
24
25 static void engine_select_add(struct IODescriptor *iofd) {
26     /* empty */
27 }
28
29 static void engine_select_remove(struct IODescriptor *iofd) {
30     /* empty */
31 }
32
33 static void engine_select_update(struct IODescriptor *iofd) {
34     /* empty */
35 }
36
37 static void engine_select_loop(struct timeval *timeout) {
38     fd_set read_fds;
39     fd_set write_fds;
40     unsigned int fds_size = 0;
41     struct IODescriptor *iofd, *tmp_iofd;
42     struct timeval now, tdiff;
43     int select_result;
44     
45     gettimeofday(&now, NULL);
46     
47     //clear fds
48     FD_ZERO(&read_fds);
49     FD_ZERO(&write_fds);
50     
51     for(iofd = first_descriptor; iofd; iofd = tmp_iofd) {
52         tmp_iofd = iofd->next;
53         if(iofd->type == IOTYPE_SERVER || iofd->type == IOTYPE_CLIENT || iofd->type == IOTYPE_STDIN) {
54             if(iofd->fd > fds_size)
55                 fds_size = iofd->fd;
56             FD_SET(iofd->fd, &read_fds);
57             if(iohandler_wants_writes(iofd))
58                 FD_SET(iofd->fd, &write_fds);
59         }
60         if(iofd->type == IOTYPE_TIMER || iofd->timeout.tv_sec || iofd->timeout.tv_usec) {
61             tdiff.tv_sec = iofd->timeout.tv_sec - now.tv_sec;
62             tdiff.tv_usec = iofd->timeout.tv_usec - now.tv_usec;
63             
64             if(tdiff.tv_sec < 0 || (tdiff.tv_sec == 0 && tdiff.tv_usec <= 0)) {
65                 //exec timer
66                 iohandler_events(iofd, 0, 0);
67                 if(iofd->type == IOTYPE_TIMER)
68                     iohandler_close(iofd);
69                 continue;
70             } else if(tdiff.tv_usec < 0) {
71                 tdiff.tv_sec--;
72                 tdiff.tv_usec += 1000000; //1 sec
73             }
74             if(timeval_is_smaler((&tdiff), timeout)) {
75                 timeout->tv_sec = tdiff.tv_sec;
76                 timeout->tv_usec = tdiff.tv_usec;
77             }
78         }
79     }
80     
81     //select system call
82     select_result = select(fds_size + 1, &read_fds, &write_fds, NULL, timeout);
83     
84     if (select_result < 0) {
85         if (errno != EINTR) {
86             //hard fail
87             return;
88         }
89     }
90     
91     gettimeofday(&now, NULL);
92     
93     //check all descriptors
94     for(iofd = first_descriptor; iofd; iofd = tmp_iofd) {
95         tmp_iofd = iofd->next;
96         if(iofd->type == IOTYPE_SERVER || iofd->type == IOTYPE_CLIENT || iofd->type == IOTYPE_STDIN) {
97             if(FD_ISSET(iofd->fd, &read_fds) || FD_ISSET(iofd->fd, &write_fds)) {
98                 iohandler_events(iofd, FD_ISSET(iofd->fd, &read_fds), FD_ISSET(iofd->fd, &write_fds));
99                 continue;
100             }
101         }
102         if(iofd->type == IOTYPE_TIMER || iofd->timeout.tv_sec || iofd->timeout.tv_usec) {
103             tdiff.tv_sec = iofd->timeout.tv_sec - now.tv_sec;
104             tdiff.tv_usec = iofd->timeout.tv_usec - now.tv_usec;
105             
106             if(tdiff.tv_sec < 0 || (tdiff.tv_sec == 0 && tdiff.tv_usec <= 0)) {
107                 //exec timer
108                 iohandler_events(iofd, 0, 0);
109                 if(iofd->type == IOTYPE_TIMER)
110                     iohandler_close(iofd);
111                 continue;
112             }
113         }
114     }
115 }
116
117 static void engine_select_cleanup() {
118     /* empty */
119 }
120
121 struct IOEngine engine_select = {
122     .name = "select",
123     .init = engine_select_init,
124     .add = engine_select_add,
125     .remove = engine_select_remove,
126     .update = engine_select_update,
127     .loop = engine_select_loop,
128     .cleanup = engine_select_cleanup,
129 };