int timer_pdomain(pdomain_t* _d) { struct presentity* presentity, *t; lock_pdomain(_d); presentity = _d->first; if (0) LOG(L_ERR, "timer_pdomain: _d=%s d->first=%p\n", _d->name->s, presentity); while(presentity) { if (timer_presentity(presentity) < 0) { LOG(L_ERR, "timer_pdomain(): Error in timer_pdomain\n"); unlock_pdomain(_d); return -1; } /* Remove the entire record * if it is empty */ if (presentity->watchers == 0 && presentity->winfo_watchers==0) { t = presentity; presentity = presentity->next; remove_presentity(_d, t); free_presentity(t); } else { presentity = presentity->next; } } unlock_pdomain(_d); return 0; }
/* * Handle a publish Request */ int handle_publish(struct sip_msg* _m, char* _domain, char* _s2) { struct pdomain* d; struct presentity *p; str p_uri = { NULL, 0 }; int changed; get_act_time(); paerrno = PA_OK; if (parse_hfs(_m) < 0) { LOG(L_ERR, "handle_publish(): Error while parsing message header\n"); goto error; } if (check_message(_m) < 0) { LOG(L_ERR, "handle_publish(): Error while checking message\n"); goto error; } d = (struct pdomain*)_domain; if (get_pres_uri(_m, &p_uri) < 0 || p_uri.s == NULL || p_uri.len == 0) { LOG(L_ERR, "handle_publish(): Error while extracting presentity URI\n"); goto error; } lock_pdomain(d); LOG(L_ERR, "handle_publish -4- p_uri=%*.s p_uri.len=%d\n", p_uri.len, p_uri.s, p_uri.len); if (find_presentity(d, &p_uri, &p) > 0) { changed = 1; if (create_presentity_only(_m, d, &p_uri, &p) < 0) { goto error2; } } /* update presentity event state */ LOG(L_ERR, "handle_publish -5- presentity=%p\n", p); if (p) publish_presentity(_m, d, p, &changed); unlock_pdomain(d); if (send_reply(_m) < 0) return -1; LOG(L_ERR, "handle_publish -8- paerrno=%d\n", paerrno); return 1; error2: unlock_pdomain(d); error: send_reply(_m); return 0; }
int handle_publish(struct sip_msg* _m, char* _domain, char* _s2) { struct pdomain* d; struct presentity *p; str p_uri = STR_NULL; str uid = STR_NULL; xcap_query_params_t xcap_params; get_act_time(); paerrno = PA_OK; if (parse_publish_hfs(_m) < 0) { LOG(L_ERR, "handle_publish(): Error while parsing message header\n"); goto error; } d = (struct pdomain*)_domain; if (get_pres_uri(_m, &p_uri) < 0 || p_uri.s == NULL || p_uri.len == 0) { LOG(L_ERR, "handle_publish(): Error while extracting presentity URI\n"); goto error; } if (get_presentity_uid(&uid, _m) < 0) { ERR("Error while extracting presentity UID\n"); goto error; } lock_pdomain(d); if (find_presentity_uid(d, &uid, &p) > 0) { memset(&xcap_params, 0, sizeof(xcap_params)); if (fill_xcap_params) fill_xcap_params(_m, &xcap_params); if (new_presentity(d, &p_uri, &uid, &xcap_params, &p) < 0) { LOG(L_ERR, "handle_publish can't create presentity\n"); goto error2; } } /* update presentity event state */ if (p) publish_presentity(_m, d, p); unlock_pdomain(d); if (send_reply(_m) < 0) return -1; return 1; error2: unlock_pdomain(d); error: send_reply(_m); return 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; }
/* * Function registers a new domain with presence agent * if the domain exists, pointer to existing structure * will be returned, otherwise a new domain will be * created */ int register_pdomain(const char* _n, pdomain_t** _d) { pdomain_t *pdomain; dlist_t* d; str s; s.s = (char*)_n; s.len = strlen(_n); if (find_dlist(&s, &d) == 0) { *_d = d->d; return 0; } if (new_dlist(&s, &d) < 0) { LOG(L_ERR, "register_pdomain(): Error while creating new domain\n"); return -1; } pdomain = d->d; lock_pdomain(pdomain); /* do not enable timer to delete presentities in it */ d->next = root; root = d; *_d = pdomain; /* Preload domain with data from database if we are gonna * to use database */ pdomain_load_presentities(pdomain); unlock_pdomain(pdomain); return 0; }
static void refresh_dialog(pa_notify_cb_param_t *cbd, struct sip_msg *m) { watcher_t *w; presentity_t *p; lock_pdomain(cbd->domain); if (get_watcher(cbd, &w, &p) >= 0) tmb.dlg_response_uac(w->dialog, m, notify_is_refresh != 0 ? IS_TARGET_REFRESH : IS_NOT_TARGET_REFRESH); unlock_pdomain(cbd->domain); }
static void destroy_subscription(pa_notify_cb_param_t *cbd) { presentity_t *p = NULL; watcher_t *w = NULL; /* if (find_pdomain(cbd->domain, &domain) != 0) { ERR("can't find PA domain\n"); return; } */ lock_pdomain(cbd->domain); if (get_watcher(cbd, &w, &p) != 0) { unlock_pdomain(cbd->domain); return; } remove_watcher(p, w); free_watcher(w); unlock_pdomain(cbd->domain); }
/* * Free all memory allocated for * the domain */ void free_pdomain(pdomain_t* _d) { int i; lock_pdomain(_d); if (_d->table) { for(i = 0; i < _d->size; i++) { deinit_slot(_d->table + i); } mem_free(_d->table); } unlock_pdomain(_d); mem_free(_d); }
int fifo_pa_watcherinfo(FILE *fifo, char *response_file) { char pdomain_s[MAX_P_URI]; char p_uri_s[MAX_P_URI]; pdomain_t *pdomain = NULL; presentity_t *presentity = NULL; str pdomain_name, p_uri; if (!read_line(pdomain_s, MAX_PDOMAIN, fifo, &pdomain_name.len) || pdomain_name.len == 0) { fifo_reply(response_file, "400 pa_watcherinfo: pdomain expected\n"); LOG(L_ERR, "ERROR: pa_watcherinfo: pdomain expected\n"); return 1; } pdomain_name.s = pdomain_s; if (!read_line(p_uri_s, MAX_P_URI, fifo, &p_uri.len) || p_uri.len == 0) { fifo_reply(response_file, "400 pa_watcherinfo: p_uri expected\n"); LOG(L_ERR, "ERROR: pa_watcherinfo: p_uri expected\n"); return 1; } p_uri.s = p_uri_s; register_pdomain(pdomain_s, &pdomain); if (!pdomain) { fifo_reply(response_file, "400 could not register pdomain\n"); LOG(L_ERR, "ERROR: pa_watcherinfo: could not register pdomain %.*s\n", pdomain_name.len, pdomain_name.s); return 1; } lock_pdomain(pdomain); find_presentity(pdomain, &p_uri, &presentity); if (presentity) { db_read_watcherinfo(presentity); } unlock_pdomain(pdomain); fifo_reply(response_file, "200 watcherinfo updated\n", "(%.*s)\n", p_uri.len, ZSW(p_uri.s)); return 1; }
/* * contact will be NULL if user is offline * fixme:locking */ void callback(str* _user, str *_contact, int state, void* data) { presentity_t *presentity; get_act_time(); presentity = (struct presentity*)data; if (presentity && callback_update_db) { presence_tuple_t *tuple = NULL; int orig; LOG(L_ERR, "callback: uri=%.*s contact=%.*s state=%d\n", presentity->uri.len, presentity->uri.s, (_contact ? _contact->len : 0), (_contact ? _contact->s : ""), state); if (_contact) { if (callback_lock_pdomain) lock_pdomain(presentity->pdomain); find_presence_tuple(_contact, presentity, &tuple); if (!tuple) { new_presence_tuple(_contact, act_time + default_expires, presentity, &tuple); add_presence_tuple(presentity, tuple); }; orig = tuple->state; if (state == 0) { tuple->state = PS_OFFLINE; } else { tuple->state = PS_ONLINE; } tuple->expires = act_time + default_expires; db_update_presentity(presentity); if (orig != state) { presentity->flags |= PFLAG_PRESENCE_CHANGED; } if (callback_lock_pdomain) unlock_pdomain(presentity->pdomain); } } }
int timer_pdomain(pdomain_t* _d) { struct presentity* presentity, *t; time_t start, stop; PROF_START(pa_timer_pdomain) lock_pdomain(_d); start = time(NULL); presentity = _d->first; while(presentity) { if (timer_presentity(presentity) < 0) { LOG(L_ERR, "timer_pdomain(): Error in timer_pdomain\n"); unlock_pdomain(_d); PROF_STOP(pa_timer_pdomain) return -1; } /* Remove the entire record * if it is empty */ if ( (!presentity->first_watcher) && (!presentity->first_winfo_watcher) && (!presentity->data.first_tuple) && (!presentity->data.first_note) && (!presentity->data.first_unknown_element) && (!presentity->first_qsa_subscription) && (presentity->ref_cnt == 0)) { LOG(L_DBG, "timer_pdomain(): removing empty presentity\n"); t = presentity; presentity = presentity->next; release_presentity(t); } else { presentity = presentity->next; } }
int fifo_pa_location_contact(FILE *fifo, char *response_file) { char pdomain_s[MAX_P_URI]; char p_uri_s[MAX_P_URI]; char p_contact_s[MAX_P_URI]; char location_s[MAX_LOCATION]; char priority_s[MAX_LOCATION]; char expires_s[MAX_LOCATION]; pdomain_t *pdomain = NULL; presentity_t *presentity = NULL; presence_tuple_t *tuple = NULL; str pdomain_name, p_uri, p_contact, location, priority_str, expires_str; time_t expires; double priority; int changed = 0; char *msg = "no error"; if (!read_line(pdomain_s, MAX_PDOMAIN, fifo, &pdomain_name.len) || pdomain_name.len == 0) { fifo_reply(response_file, "400 pa_location_contact: pdomain expected\n"); LOG(L_ERR, "ERROR: pa_location_contact: pdomain expected\n"); return 1; } pdomain_name.s = pdomain_s; if (!read_line(p_uri_s, MAX_P_URI, fifo, &p_uri.len) || p_uri.len == 0) { fifo_reply(response_file, "400 pa_location_contact: p_uri expected\n"); LOG(L_ERR, "ERROR: pa_location_contact: p_uri expected\n"); return 1; } p_uri.s = p_uri_s; if (!read_line(p_contact_s, MAX_P_URI, fifo, &p_contact.len) || p_contact.len == 0) { fifo_reply(response_file, "400 pa_location_contact: p_contact expected\n"); LOG(L_ERR, "ERROR: pa_location_contact: p_contact expected\n"); return 1; } p_contact.s = p_contact_s; if (!read_line(location_s, MAX_LOCATION, fifo, &location.len) || location.len == 0) { fifo_reply(response_file, "400 pa_location_contact: location expected\n"); LOG(L_ERR, "ERROR: pa_location_contact: location expected\n"); return 1; } location.s = location_s; if (!read_line(priority_s, MAX_LOCATION, fifo, &priority_str.len) || priority_str.len == 0) { fifo_reply(response_file, "400 pa_location_contact: priority expected\n"); LOG(L_ERR, "ERROR: pa_location_contact: priority expected\n"); return 1; } priority = strtod(priority_s, NULL); if (!read_line(expires_s, MAX_LOCATION, fifo, &expires_str.len) || expires_str.len == 0) { fifo_reply(response_file, "400 pa_location_contact: expires expected\n"); LOG(L_ERR, "ERROR: pa_location_contact: expires expected\n"); return 1; } expires = strtoul(expires_s, NULL, 0); register_pdomain(pdomain_s, &pdomain); if (!pdomain) { fifo_reply(response_file, "400 could not register pdomain\n"); LOG(L_ERR, "ERROR: pa_location_contact: could not register pdomain %.*s\n", pdomain_name.len, pdomain_name.s); return 1; } lock_pdomain(pdomain); find_presentity(pdomain, &p_uri, &presentity); if (!presentity) { new_presentity(pdomain, &p_uri, &presentity); add_presentity(pdomain, presentity); changed = 1; } if (!presentity) { msg = "400 could not find presentity\n"; LOG(L_ERR, "ERROR: pa_location_contact: could not find presentity %.*s\n", p_uri.len, p_uri.s); return 1; } find_presence_tuple(&p_contact, presentity, &tuple); if (!tuple && new_tuple_on_publish) { new_presence_tuple(&p_contact, expires, presentity, &tuple); add_presence_tuple(presentity, tuple); tuple->state = PS_ONLINE; changed = 1; } if (!tuple) { LOG(L_ERR, "publish_presentity: no tuple for %.*s\n", presentity->uri.len, presentity->uri.s); msg = "400 could not find presence tuple\n"; goto error; } changed = 1; if (1 || (tuple->location.loc.len && str_strcasecmp(&tuple->location.room, &location) != 0)) { changed = 1; LOG(L_ERR, "Setting room of contact=%.*s to %.*s\n", tuple->contact.len, tuple->contact.s, tuple->location.room.len, tuple->location.room.s); strncpy(tuple->location.room.s, location.s, location.len); tuple->location.room.len = location.len; strncpy(tuple->location.loc.s, location.s, location.len); tuple->location.loc.len = location.len; } if (tuple->priority != priority) { tuple->priority = priority; changed = 1; } if (expires < 7*24*3600) { /* must be seconds */ get_act_time(); expires = act_time + expires; } if (tuple->expires != expires) { tuple->expires = expires; changed = 1; } if (changed) { presentity->flags |= PFLAG_PRESENCE_CHANGED; } db_update_presentity(presentity); unlock_pdomain(pdomain); fifo_reply(response_file, "200 published\n", "(%.*s %.*s)\n", p_uri.len, ZSW(p_uri.s), location.len, ZSW(location.s)); return 1; error: unlock_pdomain(pdomain); fifo_reply(response_file, msg); return 1; }
int fifo_pa_location(FILE *fifo, char *response_file) { char pdomain_s[MAX_P_URI]; char p_uri_s[MAX_P_URI]; char location_s[MAX_LOCATION]; pdomain_t *pdomain = NULL; presentity_t *presentity = NULL; presence_tuple_t *tuple = NULL; str pdomain_name, p_uri, location; int changed = 0; if (!read_line(pdomain_s, MAX_PDOMAIN, fifo, &pdomain_name.len) || pdomain_name.len == 0) { fifo_reply(response_file, "400 pa_location: pdomain expected\n"); LOG(L_ERR, "ERROR: pa_location: pdomain expected\n"); return 1; } pdomain_name.s = pdomain_s; if (!read_line(p_uri_s, MAX_P_URI, fifo, &p_uri.len) || p_uri.len == 0) { fifo_reply(response_file, "400 pa_location: p_uri expected\n"); LOG(L_ERR, "ERROR: pa_location: p_uri expected\n"); return 1; } p_uri.s = p_uri_s; if (!read_line(location_s, MAX_LOCATION, fifo, &location.len) || location.len == 0) { fifo_reply(response_file, "400 pa_location: location expected\n"); LOG(L_ERR, "ERROR: pa_location: location expected\n"); return 1; } location.s = location_s; register_pdomain(pdomain_s, &pdomain); if (!pdomain) { fifo_reply(response_file, "400 could not register pdomain\n"); LOG(L_ERR, "ERROR: pa_location: could not register pdomain %.*s\n", pdomain_name.len, pdomain_name.s); return 1; } lock_pdomain(pdomain); find_presentity(pdomain, &p_uri, &presentity); if (!presentity) { new_presentity(pdomain, &p_uri, &presentity); add_presentity(pdomain, presentity); changed = 1; } if (!presentity) { unlock_pdomain(pdomain); fifo_reply(response_file, "400 could not find presentity\n"); LOG(L_ERR, "ERROR: pa_location: could not find presentity %.*s\n", p_uri.len, p_uri.s); return 1; } changed = 1; for (tuple = presentity->tuples; tuple; tuple = tuple->next) { if (tuple->location.loc.len && str_strcasecmp(&tuple->location.room, &location) != 0) changed = 1; LOG(L_ERR, "Setting room of contact=%.*s to %.*s\n", tuple->contact.len, tuple->contact.s, tuple->location.room.len, tuple->location.room.s); strncpy(tuple->location.room.s, location.s, location.len); tuple->location.room.len = location.len; strncpy(tuple->location.loc.s, location.s, location.len); tuple->location.loc.len = location.len; } if (changed) { presentity->flags |= PFLAG_PRESENCE_CHANGED; } db_update_presentity(presentity); unlock_pdomain(pdomain); fifo_reply(response_file, "200 published\n", "(%.*s %.*s)\n", p_uri.len, ZSW(p_uri.s), location.len, ZSW(location.s)); return 1; }
/* * Handle a subscribe Request */ int handle_subscription(struct sip_msg* _m, char* _domain, char* _s2) { struct pdomain* d; struct presentity *p; struct watcher* w; str p_uri; LOG(L_ERR, "handle_subscription() entered\n"); get_act_time(); paerrno = PA_OK; if (parse_hfs(_m, 1) < 0) { LOG(L_ERR, "handle_subscription(): Error while parsing message header\n"); goto error; } if (check_message(_m) < 0) { LOG(L_ERR, "handle_subscription(): Error while checking message\n"); goto error; } d = (struct pdomain*)_domain; if (get_pres_uri(_m, &p_uri) < 0) { LOG(L_ERR, "handle_subscription(): Error while extracting presentity URI\n"); goto error; } lock_pdomain(d); if (find_presentity(d, &p_uri, &p) > 0) { if (create_presentity(_m, d, &p_uri, &p, &w) < 0) { LOG(L_ERR, "handle_subscription(): Error while creating new presentity\n"); goto error2; } } else { if (update_presentity(_m, d, p, &w) < 0) { LOG(L_ERR, "handle_subscription(): Error while updating presentity\n"); goto error2; } } if (send_reply(_m) < 0) { LOG(L_ERR, "handle_subscription(): Error while sending reply\n"); goto error2; } if (p) { p->flags |= PFLAG_WATCHERINFO_CHANGED; } if (w) { w->flags |= WFLAG_SUBSCRIPTION_CHANGED; } LOG(L_ERR, "handle_subscription about to return 1: w->event_package=%d w->accept=%d p->flags=%x w->flags=%x w=%p\n", (w ? w->event_package : -1), (w ? w->accept : -1), (p ? p->flags : -1), (w ? w->flags : -1), w); unlock_pdomain(d); return 1; error2: LOG(L_ERR, "handle_subscription about to return -1\n"); unlock_pdomain(d); return -1; error: LOG(L_ERR, "handle_subscription about to send_reply and return -2\n"); send_reply(_m); return -1; }
int pa_handle_registration(struct sip_msg* _m, char* _domain, char* _s2) { struct pdomain* d = (struct pdomain*)_domain; struct presentity *presentity; str p_uri; struct to_body *from = NULL; int e = 0; // LOG(L_ERR, "pa_handle_registration() entered\n"); paerrno = PA_OK; d = (struct pdomain*)_domain; if (parse_hfs(_m, 0) < 0) { paerrno = PA_PARSE_ERR; LOG(L_ERR, "pa_handle_registration(): Error while parsing headers\n"); return -1; } from = get_from(_m); if (!from || (pa_extract_aor(&from->uri, &p_uri) < 0)) { LOG(L_ERR, "pa_handle_registration(): Error while extracting Address Of Record\n"); goto error; } if (_m->expires) { e = ((exp_body_t*)_m->expires->parsed)->val; } if (from) LOG(L_ERR, "pa_handle_registration: from=%.*s p_uri=%.*s expires=%d\n", from->uri.len, from->uri.s, p_uri.len, p_uri.s, e); lock_pdomain(d); if (find_presentity(d, &p_uri, &presentity) > 0) { LOG(L_ERR, "pa_handle_registration: find_presentity did not find presentity\n"); if (e > 0) { if (create_presentity_only(_m, d, &p_uri, &presentity) < 0) { LOG(L_ERR, "pa_handle_registration(): Error while creating new presentity\n"); goto error2; } } #if 0 else { presence_tuple_t *tuple = NULL; if (_m->contact) { struct hdr_field* ptr = _m->contact; while (ptr) { if (ptr->type == HDR_CONTACT) { if (!ptr->parsed && (parse_contact(ptr) < 0)) { goto next; } } if (find_presence_tuple(contact, presentity, &tuple) == 0) { tuple->state = PS_OFFLINE; } next: ptr = ptr->next; } } db_update_presentity(presentity); } #endif } if (presentity && e > 0) { LOG(L_ERR, "pa_handle_registration about to call d->reg p=%p expires=%d", presentity, e); d->reg(&presentity->uri, &presentity->uri, (void*)callback, presentity); } LOG(L_ERR, "pa_handle_registration about to return 1"); unlock_pdomain(d); return 1; error2: LOG(L_ERR, "pa_handle_registration about to return -1\n"); unlock_pdomain(d); return -1; error: LOG(L_ERR, "pa_handle_registration about to return -2\n"); return -1; }