static DBusMessage *unregister_watcher(DBusConnection *conn, DBusMessage *msg, void *data) { struct heartrate_adapter *hradapter = data; struct watcher *watcher; const char *sender = dbus_message_get_sender(msg); char *path; if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID)) return btd_error_invalid_args(msg); watcher = find_watcher(hradapter->watchers, sender, path); if (watcher == NULL) return btd_error_does_not_exist(msg); hradapter->watchers = g_slist_remove(hradapter->watchers, watcher); g_dbus_remove_watch(conn, watcher->id); if (g_slist_length(hradapter->watchers) == 0) g_slist_foreach(hradapter->devices, disable_measurement, 0); DBG("heartrate watcher [%s] unregistered", path); return dbus_message_new_method_return(msg); }
static DBusMessage *register_watcher(DBusConnection *conn, DBusMessage *msg, void *data) { struct heartrate_adapter *hradapter = data; struct watcher *watcher; const char *sender = dbus_message_get_sender(msg); char *path; if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID)) return btd_error_invalid_args(msg); watcher = find_watcher(hradapter->watchers, sender, path); if (watcher != NULL) return btd_error_already_exists(msg); watcher = g_new0(struct watcher, 1); watcher->hradapter = hradapter; watcher->id = g_dbus_add_disconnect_watch(conn, sender, watcher_exit_cb, watcher, destroy_watcher); watcher->srv = g_strdup(sender); watcher->path = g_strdup(path); if (g_slist_length(hradapter->watchers) == 0) g_slist_foreach(hradapter->devices, enable_measurement, 0); hradapter->watchers = g_slist_prepend(hradapter->watchers, watcher); DBG("heartrate watcher [%s] registered", path); return dbus_message_new_method_return(msg); }
static void uv__inotify_read(uv_loop_t* loop, uv__io_t* dummy, unsigned int events) { const struct uv__inotify_event* e; struct watcher_list* w; uv_fs_event_t* h; QUEUE queue; QUEUE* q; const char* path; ssize_t size; const char *p; /* needs to be large enough for sizeof(inotify_event) + strlen(path) */ char buf[4096]; while (1) { do size = read(loop->inotify_fd, buf, sizeof(buf)); while (size == -1 && errno == EINTR); if (size == -1) { assert(errno == EAGAIN || errno == EWOULDBLOCK); break; } assert(size > 0); /* pre-2.6.21 thing, size=0 == read buffer too small */ /* Now we have one or more inotify_event structs. */ for (p = buf; p < buf + size; p += sizeof(*e) + e->len) { e = (const struct uv__inotify_event*)p; events = 0; if (e->mask & (UV__IN_ATTRIB|UV__IN_MODIFY)) events |= UV_CHANGE; if (e->mask & ~(UV__IN_ATTRIB|UV__IN_MODIFY)) events |= UV_RENAME; w = find_watcher(loop, e->wd); if (w == NULL) continue; /* Stale event, no watchers left. */ /* inotify does not return the filename when monitoring a single file * for modifications. Repurpose the filename for API compatibility. * I'm not convinced this is a good thing, maybe it should go. */ path = e->len ? (const char*) (e + 1) : uv__basename_r(w->path); QUEUE_MOVE(&w->watchers, &queue); while (!QUEUE_EMPTY(&queue)) { q = QUEUE_HEAD(&queue); h = QUEUE_DATA(q, uv_fs_event_t, watchers); QUEUE_REMOVE(q); QUEUE_INSERT_TAIL(&w->watchers, q); h->cb(h, path, events, 0); } } } }
/* * Returns 1 if subscription exists and -1 if not */ int existing_subscription(struct sip_msg* _m, char* _domain, char* _s2) { struct pdomain* d; struct presentity* p; struct watcher* w; str p_uri, w_uri; str w_dn; int et = 0; if (_m->event) { event_t *event = (event_t*)(_m->event->parsed); et = event->parsed; } else { LOG(L_ERR, "existing_subscription defaulting to EVENT_PRESENCE\n"); et = EVENT_PRESENCE; } paerrno = PA_OK; if (parse_from_header(_m) < 0) { paerrno = PA_PARSE_ERR; LOG(L_ERR, "existing_subscription(): Error while parsing From header field\n"); goto error; } d = (struct pdomain*)_domain; if (get_pres_uri(_m, &p_uri) < 0) { LOG(L_ERR, "existing_subscription(): Error while extracting presentity URI\n"); goto error; } if (get_watch_uri(_m, &w_uri, &w_dn) < 0) { LOG(L_ERR, "existing_subscription(): Error while extracting watcher URI\n"); goto error; } lock_pdomain(d); if (find_presentity(d, &p_uri, &p) == 0) { if (find_watcher(p, &w_uri, et, &w) == 0) { LOG(L_ERR, "existing_subscription() found watcher\n"); unlock_pdomain(d); return 1; } } unlock_pdomain(d); return -1; error: send_reply(_m); return 0; }
int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb, const char* path, unsigned int flags) { struct watcher_list* w; int events; int err; int wd; if (uv__is_active(handle)) return -EINVAL; err = init_inotify(handle->loop); if (err) return err; events = UV__IN_ATTRIB | UV__IN_CREATE | UV__IN_MODIFY | UV__IN_DELETE | UV__IN_DELETE_SELF | UV__IN_MOVE_SELF | UV__IN_MOVED_FROM | UV__IN_MOVED_TO; wd = uv__inotify_add_watch(handle->loop->inotify_fd, path, events); if (wd == -1) return -errno; w = find_watcher(handle->loop, wd); if (w) goto no_insert; w = uv__malloc(sizeof(*w) + strlen(path) + 1); if (w == NULL) return -ENOMEM; w->wd = wd; w->path = strcpy((char*)(w + 1), path); QUEUE_INIT(&w->watchers); w->iterating = 0; RB_INSERT(watcher_root, CAST(&handle->loop->inotify_watchers), w); no_insert: uv__handle_start(handle); QUEUE_INSERT_TAIL(&w->watchers, &handle->watchers); handle->path = w->path; handle->cb = cb; handle->wd = wd; return 0; }
static void uv__inotify_read(EV_P_ ev_io* w, int revents) { const struct inotify_event* e; uv_fs_event_t* handle; uv_loop_t* uv_loop; const char* filename; ssize_t size; int events; const char *p; /* needs to be large enough for sizeof(inotify_event) + strlen(filename) */ char buf[4096]; uv_loop = container_of(w, uv_loop_t, inotify_read_watcher); while (1) { do { size = read(uv_loop->inotify_fd, buf, sizeof buf); } while (size == -1 && errno == EINTR); if (size == -1) { assert(errno == EAGAIN || errno == EWOULDBLOCK); break; } assert(size > 0); /* pre-2.6.21 thing, size=0 == read buffer too small */ /* Now we have one or more inotify_event structs. */ for (p = buf; p < buf + size; p += sizeof(*e) + e->len) { e = (const struct inotify_event*)p; events = 0; if (e->mask & (IN_ATTRIB|IN_MODIFY)) events |= UV_CHANGE; if (e->mask & ~(IN_ATTRIB|IN_MODIFY)) events |= UV_RENAME; handle = find_watcher(uv_loop, e->wd); if (handle == NULL) continue; /* Handle has already been closed. */ /* inotify does not return the filename when monitoring a single file * for modifications. Repurpose the filename for API compatibility. * I'm not convinced this is a good thing, maybe it should go. */ filename = e->len ? (const char*) (e + 1) : basename_r(handle->filename); handle->cb(handle, filename, events, 0); } } }
int uv_fs_event_stop(uv_fs_event_t* handle) { struct watcher_list* w; if (!uv__is_active(handle)) return 0; w = find_watcher(handle->loop, handle->wd); assert(w != NULL); handle->wd = -1; handle->path = NULL; uv__handle_stop(handle); QUEUE_REMOVE(&handle->watchers); maybe_free_watcher_list(w, handle->loop); return 0; }
int uv_fs_event_stop(uv_fs_event_t* handle) { struct watcher_list* w; if (!uv__is_active(handle)) return 0; w = find_watcher(handle->loop, handle->wd); assert(w != NULL); handle->wd = -1; handle->path = NULL; uv__handle_stop(handle); QUEUE_REMOVE(&handle->watchers); if (QUEUE_EMPTY(&w->watchers)) { /* No watchers left for this path. Clean up. */ RB_REMOVE(watcher_root, CAST(&handle->loop->inotify_watchers), w); uv__inotify_rm_watch(handle->loop->inotify_fd, w->wd); uv__free(w); } return 0; }
/* * Update existing presentity and watcher list */ static int update_presentity(struct sip_msg* _m, struct pdomain* _d, struct presentity* _p, struct watcher** _w) { time_t e; dlg_t* dialog; str watch_uri; str watch_dn; event_t *event = NULL; int et = 0; if (_m->event) { event = (event_t*)(_m->event->parsed); et = event->parsed; } else { LOG(L_ERR, "update_presentity defaulting to EVENT_PRESENCE\n"); et = EVENT_PRESENCE; } if (_m->expires) { e = ((exp_body_t*)_m->expires->parsed)->val; } else { e = default_expires; } if (get_watch_uri(_m, &watch_uri, &watch_dn) < 0) { LOG(L_ERR, "update_presentity(): Error while extracting watcher URI\n"); return -1; } if (find_watcher(_p, &watch_uri, et, _w) == 0) { LOG(L_ERR, "update_presentity() found watcher\n"); if (e == 0) { if (et != EVENT_PRESENCE_WINFO) { if (remove_watcher(_p, *_w) < 0) { LOG(L_ERR, "update_presentity(): Error while deleting winfo watcher\n"); return -2; } } else { if (remove_winfo_watcher(_p, *_w) < 0) { LOG(L_ERR, "update_presentity(): Error while deleting winfo watcher\n"); return -2; } } (*_w)->expires = 0; /* The watcher will be freed after NOTIFY is sent */ if (!_p->watchers && !_p->winfo_watchers) { remove_presentity(_d, _p); } } else { e += act_time; if (update_watcher(*_w, e) < 0) { LOG(L_ERR, "update_presentity(): Error while updating watcher\n"); return -3; } } } else { if (e) { e += act_time; if (tmb.new_dlg_uas(_m, 200, &dialog) < 0) { paerrno = PA_DIALOG_ERR; LOG(L_ERR, "update_presentity(): Error while creating dialog state\n"); return -4; } if (et != EVENT_PRESENCE_WINFO) { if (add_watcher(_p, &watch_uri, e, et, acc, dialog, &watch_dn, _w) < 0) { LOG(L_ERR, "update_presentity(): Error while creating presentity\n"); tmb.free_dlg(dialog); return -5; } } else { if (add_winfo_watcher(_p, &watch_uri, e, et, acc, dialog, &watch_dn, _w) < 0) { LOG(L_ERR, "update_presentity(): Error while creating winfo watcher\n"); tmb.free_dlg(dialog); return -5; } } } else { DBG("update_presentity(): expires = 0 but no watcher found\n"); *_w = 0; } } return 0; }
static void uv__inotify_read(uv_loop_t* loop, uv__io_t* dummy, unsigned int events) { const struct uv__inotify_event* e; struct watcher_list* w; uv_fs_event_t* h; QUEUE queue; QUEUE* q; const char* path; ssize_t size; const char *p; /* needs to be large enough for sizeof(inotify_event) + strlen(path) */ char buf[4096]; while (1) { do size = read(loop->inotify_fd, buf, sizeof(buf)); while (size == -1 && errno == EINTR); if (size == -1) { assert(errno == EAGAIN || errno == EWOULDBLOCK); break; } assert(size > 0); /* pre-2.6.21 thing, size=0 == read buffer too small */ /* Now we have one or more inotify_event structs. */ for (p = buf; p < buf + size; p += sizeof(*e) + e->len) { e = (const struct uv__inotify_event*)p; events = 0; if (e->mask & (UV__IN_ATTRIB|UV__IN_MODIFY)) events |= UV_CHANGE; if (e->mask & ~(UV__IN_ATTRIB|UV__IN_MODIFY)) events |= UV_RENAME; w = find_watcher(loop, e->wd); if (w == NULL) continue; /* Stale event, no watchers left. */ /* inotify does not return the filename when monitoring a single file * for modifications. Repurpose the filename for API compatibility. * I'm not convinced this is a good thing, maybe it should go. */ path = e->len ? (const char*) (e + 1) : uv__basename_r(w->path); /* We're about to iterate over the queue and call user's callbacks. * What can go wrong? * A callback could call uv_fs_event_stop() * and the queue can change under our feet. * So, we use QUEUE_MOVE() trick to safely iterate over the queue. * And we don't free the watcher_list until we're done iterating. * * First, * tell uv_fs_event_stop() (that could be called from a user's callback) * not to free watcher_list. */ w->iterating = 1; QUEUE_MOVE(&w->watchers, &queue); while (!QUEUE_EMPTY(&queue)) { q = QUEUE_HEAD(&queue); h = QUEUE_DATA(q, uv_fs_event_t, watchers); QUEUE_REMOVE(q); QUEUE_INSERT_TAIL(&w->watchers, q); h->cb(h, path, events, 0); } /* done iterating, time to (maybe) free empty watcher_list */ w->iterating = 0; maybe_free_watcher_list(w, loop); } } }