added session manager and support for an external login system
[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             }
100         }
101         if(iofd->type == IOTYPE_TIMER || iofd->timeout.tv_sec || iofd->timeout.tv_usec) {
102             tdiff.tv_sec = iofd->timeout.tv_sec - now.tv_sec;
103             tdiff.tv_usec = iofd->timeout.tv_usec - now.tv_usec;
104             
105             if(tdiff.tv_sec < 0 || (tdiff.tv_sec == 0 && tdiff.tv_usec <= 0)) {
106                 //exec timer
107                 iohandler_events(iofd, 0, 0);
108                 if(iofd->type == IOTYPE_TIMER)
109                     iohandler_close(iofd);
110                 continue;
111             }
112         }
113     }
114 }
115
116 static void engine_select_cleanup() {
117     /* empty */
118 }
119
120 struct IOEngine engine_select = {
121     .name = "select",
122     .init = engine_select_init,
123     .add = engine_select_add,
124     .remove = engine_select_remove,
125     .update = engine_select_update,
126     .loop = engine_select_loop,
127     .cleanup = engine_select_cleanup,
128 };