1 /* 2 Unix SMB/CIFS implementation. 3 main select loop and event handling 4 wrapper for http://git.lysator.liu.se/liboop/ 5 6 Copyright (C) Stefan Metzmacher 2005 7 8 ** NOTE! The following LGPL license applies to the tevent 9 ** library. This does NOT imply that all of Samba is released 10 ** under the LGPL 11 12 This library is free software; you can redistribute it and/or 13 modify it under the terms of the GNU Lesser General Public 14 License as published by the Free Software Foundation; either 15 version 3 of the License, or (at your option) any later version. 16 17 This library is distributed in the hope that it will be useful, 18 but WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 Lesser General Public License for more details. 21 22 You should have received a copy of the GNU Lesser General Public 23 License along with this library; if not, see <http://www.gnu.org/licenses/>. 24 */ 25 26 #include "events.h" 27 #include "events_internal.h" 28 29 #include <oop.h> 30 31 /* 32 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 33 34 NOTE: this code compiles fine, but is completely *UNTESTED* 35 and is only committed as an example 36 37 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 38 */ 39 40 static int oop_event_context_destructor(struct tevent_context *ev) 41 { 42 oop_source_sys *oop_sys = ev->additional_data; 43 44 oop_sys_delete(oop_sys); 45 46 return 0; 47 } 48 49 /* 50 create a oop_event_context structure. 51 */ 52 static int oop_event_context_init(struct tevent_context *ev, void *private_data) 53 { 54 oop_source_sys *oop_sys = private_data; 55 56 if (!oop_sys) { 57 oop_sys = oop_sys_new(); 58 if (!oop_sys) { 59 return -1; 60 } 61 62 talloc_set_destructor(ev, oop_event_context_destructor); 63 } 64 65 ev->additional_data = oop_sys; 66 67 return 0; 68 } 69 70 static void *oop_event_fd_handler(oop_source *oop, int fd, oop_event oop_type, void *ptr) 71 { 72 struct tevent_fd *fde = ptr; 73 74 if (fd != fde->fd) return OOP_ERROR; 75 76 switch(oop_type) { 77 case OOP_READ: 78 fde->handler(fde->event_ctx, fde, EVENT_FD_READ, fde->private_data); 79 return OOP_CONTINUE; 80 case OOP_WRITE: 81 fde->handler(fde->event_ctx, fde, EVENT_FD_WRITE, fde->private_data); 82 return OOP_CONTINUE; 83 case OOP_EXCEPTION: 84 return OOP_ERROR; 85 case OOP_NUM_EVENTS: 86 return OOP_ERROR; 87 } 88 89 return OOP_ERROR; 90 } 91 92 /* 93 destroy an fd_event 94 */ 95 static int oop_event_fd_destructor(struct tevent_fd *fde) 96 { 97 struct tevent_context *ev = fde->event_ctx; 98 oop_source_sys *oop_sys = ev->additional_data; 99 oop_source *oop = oop_sys_source(oop_sys); 100 101 if (fde->flags & EVENT_FD_READ) 102 oop->cancel_fd(oop, fde->fd, OOP_READ); 103 if (fde->flags & EVENT_FD_WRITE) 104 oop->cancel_fd(oop, fde->fd, OOP_WRITE); 105 106 if (fde->flags & EVENT_FD_AUTOCLOSE) { 107 close(fde->fd); 108 fde->fd = -1; 109 } 110 111 return 0; 112 } 113 114 /* 115 add a fd based event 116 return NULL on failure (memory allocation error) 117 */ 118 static struct tevent_fd *oop_event_add_fd(struct tevent_context *ev, TALLOC_CTX *mem_ctx, 119 int fd, uint16_t flags, 120 event_fd_handler_t handler, 121 void *private_data) 122 { 123 struct tevent_fd *fde; 124 oop_source_sys *oop_sys = ev->additional_data; 125 oop_source *oop = oop_sys_source(oop_sys); 126 127 fde = talloc(mem_ctx?mem_ctx:ev, struct tevent_fd); 128 if (!fde) return NULL; 129 130 fde->event_ctx = ev; 131 fde->fd = fd; 132 fde->flags = flags; 133 fde->handler = handler; 134 fde->private_data = private_data; 135 fde->additional_flags = 0; 136 fde->additional_data = NULL; 137 138 if (fde->flags & EVENT_FD_READ) 139 oop->on_fd(oop, fde->fd, OOP_READ, oop_event_fd_handler, fde); 140 if (fde->flags & EVENT_FD_WRITE) 141 oop->on_fd(oop, fde->fd, OOP_WRITE, oop_event_fd_handler, fde); 142 143 talloc_set_destructor(fde, oop_event_fd_destructor); 144 145 return fde; 146 } 147 148 /* 149 return the fd event flags 150 */ 151 static uint16_t oop_event_get_fd_flags(struct tevent_fd *fde) 152 { 153 return fde->flags; 154 } 155 156 /* 157 set the fd event flags 158 */ 159 static void oop_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags) 160 { 161 oop_source_sys *oop_sys; 162 oop_source *oop; 163 164 oop_sys = fde->event_ctx->additional_data; 165 oop = oop_sys_source(oop_sys); 166 167 if ((fde->flags & EVENT_FD_READ)&&(!(flags & EVENT_FD_READ))) 168 oop->cancel_fd(oop, fde->fd, OOP_READ); 169 170 if ((!(fde->flags & EVENT_FD_READ))&&(flags & EVENT_FD_READ)) 171 oop->on_fd(oop, fde->fd, OOP_READ, oop_event_fd_handler, fde); 172 173 if ((fde->flags & EVENT_FD_WRITE)&&(!(flags & EVENT_FD_WRITE))) 174 oop->cancel_fd(oop, fde->fd, OOP_WRITE); 175 176 if ((!(fde->flags & EVENT_FD_WRITE))&&(flags & EVENT_FD_WRITE)) 177 oop->on_fd(oop, fde->fd, OOP_WRITE, oop_event_fd_handler, fde); 178 179 fde->flags = flags; 180 } 181 182 static int oop_event_timed_destructor(struct tevent_timer *te); 183 184 static int oop_event_timed_deny_destructor(struct tevent_timer *te) 185 { 186 return -1; 187 } 188 189 static void *oop_event_timed_handler(oop_source *oop, struct timeval t, void *ptr) 190 { 191 struct tevent_timer *te = ptr; 192 193 /* deny the handler to free the event */ 194 talloc_set_destructor(te, oop_event_timed_deny_destructor); 195 te->handler(te->event_ctx, te, t, te->private_data); 196 197 talloc_set_destructor(te, oop_event_timed_destructor); 198 talloc_free(te); 199 200 return OOP_CONTINUE; 201 } 202 203 /* 204 destroy a timed event 205 */ 206 static int oop_event_timed_destructor(struct tevent_timer *te) 207 { 208 struct tevent_context *ev = te->event_ctx; 209 oop_source_sys *oop_sys = ev->additional_data; 210 oop_source *oop = oop_sys_source(oop_sys); 211 212 oop->cancel_time(oop, te->next_event, oop_event_timed_handler, te); 213 214 return 0; 215 } 216 217 /* 218 add a timed event 219 return NULL on failure (memory allocation error) 220 */ 221 static struct tevent_timer *oop_event_add_timed(struct tevent_context *ev, TALLOC_CTX *mem_ctx, 222 struct timeval next_event, 223 event_timed_handler_t handler, 224 void *private_data) 225 { 226 oop_source_sys *oop_sys = ev->additional_data; 227 oop_source *oop = oop_sys_source(oop_sys); 228 struct tevent_timer *te; 229 230 te = talloc(mem_ctx?mem_ctx:ev, struct tevent_timer); 231 if (te == NULL) return NULL; 232 233 te->event_ctx = ev; 234 te->next_event = next_event; 235 te->handler = handler; 236 te->private_data = private_data; 237 te->additional_data = NULL; 238 239 oop->on_time(oop, te->next_event, oop_event_timed_handler, te); 240 241 talloc_set_destructor(te, oop_event_timed_destructor); 242 243 return te; 244 } 245 246 /* 247 do a single event loop using the events defined in ev 248 */ 249 static int oop_event_loop_once(struct tevent_context *ev) 250 { 251 void *oop_ret; 252 oop_source_sys *oop_sys = ev->additional_data; 253 254 oop_ret = oop_sys_run_once(oop_sys); 255 if (oop_ret == OOP_CONTINUE) { 256 return 0; 257 } 258 259 return -1; 260 } 261 262 /* 263 return on failure or (with 0) if all fd events are removed 264 */ 265 static int oop_event_loop_wait(struct tevent_context *ev) 266 { 267 void *oop_ret; 268 oop_source_sys *oop_sys = ev->additional_data; 269 270 oop_ret = oop_sys_run(oop_sys); 271 if (oop_ret == OOP_CONTINUE) { 272 return 0; 273 } 274 275 return -1; 276 } 277 278 static const struct event_ops event_oop_ops = { 279 .context_init = oop_event_context_init, 280 .add_fd = oop_event_add_fd, 281 .get_fd_flags = oop_event_get_fd_flags, 282 .set_fd_flags = oop_event_set_fd_flags, 283 .add_timer = oop_event_add_timed, 284 .add_signal = common_event_add_signal, 285 .loop_once = oop_event_loop_once, 286 .loop_wait = oop_event_loop_wait, 287 }; 288 289 const struct event_ops *event_liboop_get_ops(void) 290 { 291 return &event_oop_ops; 292 } 293