int poller_update_item(struct poller *p, struct poller_item *i) { struct poller_item_int *np; if (!p || !i) return -1; if (i->fd < 0) return -1; if (!i->readable && !i->writeable) return -1; if (!i->closed) return -1; mutex_lock(&p->lock); if (i->fd >= p->items_size || !(np = p->items[i->fd])) return __poller_add_item(p, i, 1); obj_hold_o(i->obj); obj_put_o(np->item.obj); np->item.obj = i->obj; np->item.uintp = i->uintp; np->item.readable = i->readable; np->item.writeable = i->writeable; np->item.closed = i->closed; /* updating timer is not supported */ mutex_unlock(&p->lock); return 0; }
int udp_listener_init(struct udp_listener *u, struct poller *p, const endpoint_t *ep, udp_listener_callback_t func, struct obj *obj) { struct poller_item i; struct udp_listener_callback *cb; cb = obj_alloc("udp_listener_callback", sizeof(*cb), NULL); cb->func = func; cb->p = obj_get_o(obj); cb->ul = u; if (open_socket(&u->sock, SOCK_DGRAM, ep->port, &ep->address)) goto fail; ipv6only(u->sock.fd, 1); ZERO(i); i.fd = u->sock.fd; i.closed = udp_listener_closed; i.readable = udp_listener_incoming; i.obj = &cb->obj; if (poller_add_item(p, &i)) goto fail; return 0; fail: close_socket(&u->sock); obj_put_o(obj); obj_put(cb); return -1; }
/* timers_lock and timers_add_del_lock must be held */ static void poller_timers_mod(struct poller *p) { GSList *l, **ll, **kk; struct timer_item *ti, *tj; ll = &p->timers_add; while (*ll) { l = *ll; *ll = l->next; l->next = p->timers; p->timers = l; } ll = &p->timers_del; while (*ll) { ti = (*ll)->data; kk = &p->timers; while (*kk) { tj = (*kk)->data; if (tj->func != ti->func) goto next; if (tj->obj_ptr != ti->obj_ptr) goto next; goto found; next: kk = &(*kk)->next; } /* deleted a timer that wasn't added yet. possible race, otherwise bug */ ll = &(*ll)->next; continue; found: l = *ll; *ll = (*ll)->next; obj_put_o(l->data); g_slist_free_1(l); l = *kk; *kk = (*kk)->next; obj_put_o(l->data); g_slist_free_1(l); } }
int udp_listener_init(struct udp_listener *u, struct poller *p, struct in6_addr ip, u_int16_t port, udp_listener_callback_t func, struct obj *obj) { struct sockaddr_in6 sin; struct poller_item i; struct udp_listener_callback *cb; cb = obj_alloc("udp_listener_callback", sizeof(*cb), NULL); cb->func = func; cb->p = obj_get_o(obj); u->fd = socket(AF_INET6, SOCK_DGRAM, 0); if (u->fd == -1) goto fail; nonblock(u->fd); reuseaddr(u->fd); ipv6only(u->fd, 0); ZERO(sin); sin.sin6_family = AF_INET6; sin.sin6_addr = ip; sin.sin6_port = htons(port); if (bind(u->fd, (struct sockaddr *) &sin, sizeof(sin))) goto fail; ZERO(i); i.fd = u->fd; i.closed = udp_listener_closed; i.readable = udp_listener_incoming; i.obj = &cb->obj; if (poller_add_item(p, &i)) goto fail; return 0; fail: if (u->fd != -1) close(u->fd); obj_put_o(obj); obj_put(cb); return -1; }
static void poller_item_free(void *p) { struct poller_item_int *i = p; obj_put_o(i->item.obj); }
static void timer_item_free(void *p) { struct timer_item *i = p; if (i->obj_ptr) obj_put_o(i->obj_ptr); }