int process_body(str notify_body, udomain_t * domain) { xmlDocPtr doc= NULL; xmlNodePtr doc_root = NULL, registrations = NULL, contacts = NULL, uris = NULL; char uri[MAX_URI_SIZE]; str aor_key = {0, 0}; str aor = {0, 0}; str callid = {0, 0}; str contact_uri = {0, 0}; str received = {0,0}; str path = {0,0}; str user_agent = {0, 0}; int state, event, expires, result, final_result = RESULT_ERROR; char * expires_char, * cseq_char; int cseq = 0; urecord_t * ul_record; ucontact_t * ul_contact; struct sip_uri parsed_aor; /* Temporary */ int mem_only = 1; doc = xmlParseMemory(notify_body.s, notify_body.len); if(doc== NULL) { LM_ERR("Error while parsing the xml body message, Body is:\n%.*s\n", notify_body.len, notify_body.s); return -1; } doc_root = xmlGetNodeByName(doc->children, "reginfo"); if(doc_root == NULL) { LM_ERR("while extracting the reginfo node\n"); goto error; } registrations = doc_root->children; while (registrations) { /* Only process registration sub-items */ if (xmlStrcasecmp(registrations->name, BAD_CAST "registration") != 0) goto next_registration; state = reginfo_parse_state(xmlGetAttrContentByName(registrations, "state")); if (state == STATE_UNKNOWN) { LM_ERR("No state for this contact!\n"); goto next_registration; } aor.s = xmlGetAttrContentByName(registrations, "aor"); if (aor.s == NULL) { LM_ERR("No AOR for this contact!\n"); goto next_registration; } aor.len = strlen(aor.s); LM_DBG("AOR %.*s has state \"%d\"\n", aor.len, aor.s, state); /* Get username part of the AOR, search for @ in the AOR. */ if (parse_uri(aor.s, aor.len, &parsed_aor) < 0) { LM_ERR("failed to parse Address of Record (%.*s)\n", aor.len, aor.s); goto next_registration; } if (reginfo_use_domain) { aor_key.s = uri; } else { aor_key.s = parsed_aor.user.s; } aor_key.len = strlen(aor_key.s); /* Now let's lock that domain for this AOR: */ ul.lock_udomain(domain, &aor_key); /* and retrieve the user-record for this user: */ result = ul.get_urecord(domain, &aor_key, &ul_record); if (result < 0) { ul.unlock_udomain(domain, &aor_key); LM_ERR("failed to query usrloc (AOR %.*s)\n", aor_key.len, aor_key.s); goto next_registration; } /* If no contacts found, then set the ul_record to NULL */ if (result != 0) ul_record = NULL; /* If the state is terminated, we just can delete all bindings */ if (state == STATE_TERMINATED) { if (ul_record) { ul_contact = ul_record->contacts; while(ul_contact) { if (mem_only) { ul_contact->flags |= FL_MEM; } else { ul_contact->flags &= ~FL_MEM; } ul_contact = ul_contact->next; } if (ul.delete_urecord(domain, &aor_key, ul_record) < 0) { LM_ERR("failed to remove record from usrloc\n"); } /* If already a registration with contacts was found, then keep that result. otherwise the result is now "No contacts found" */ if (final_result != RESULT_CONTACTS_FOUND) final_result = RESULT_NO_CONTACTS; } /* Otherwise, process the content */ } else { /* Now lets process the Contact's from this Registration: */ contacts = registrations->children; while (contacts) { if (xmlStrcasecmp(contacts->name, BAD_CAST "contact") != 0) goto next_contact; callid.s = xmlGetAttrContentByName(contacts, "callid"); if (callid.s == NULL) { LM_ERR("No Call-ID for this contact!\n"); goto next_contact; } callid.len = strlen(callid.s); received.s = xmlGetAttrContentByName(contacts, "received"); if (received.s == NULL) { LM_DBG("No received for this contact!\n"); received.len = 0; } else { received.len = strlen(received.s); } path.s = xmlGetAttrContentByName(contacts, "path"); if (path.s == NULL) { LM_DBG("No path for this contact!\n"); path.len = 0; } else { path.len = strlen(path.s); } user_agent.s = xmlGetAttrContentByName(contacts, "user_agent"); if (user_agent.s == NULL) { LM_DBG("No user_agent for this contact!\n"); user_agent.len = 0; } else { user_agent.len = strlen(user_agent.s); } event = reginfo_parse_event(xmlGetAttrContentByName(contacts, "event")); if (event == EVENT_UNKNOWN) { LM_ERR("No event for this contact!\n"); goto next_contact; } expires_char = xmlGetAttrContentByName(contacts, "expires"); if (expires_char == NULL) { LM_ERR("No expires for this contact!\n"); goto next_contact; } expires = atoi(expires_char); if (expires < 0) { LM_ERR("No valid expires for this contact!\n"); goto next_contact; } LM_DBG("%.*s: Event \"%d\", expires %d\n", callid.len, callid.s, event, expires); cseq_char = xmlGetAttrContentByName(contacts, "cseq"); if (cseq_char == NULL) { LM_WARN("No cseq for this contact!\n"); } else { cseq = atoi(cseq_char); if (cseq < 0) { LM_WARN("No valid cseq for this contact!\n"); } } /* Now lets process the URI's from this Contact: */ uris = contacts->children; while (uris) { if (xmlStrcasecmp(uris->name, BAD_CAST "uri") != 0) goto next_uri; contact_uri.s = (char*)xmlNodeGetContent(uris); if (contact_uri.s == NULL) { LM_ERR("No URI for this contact!\n"); goto next_registration; } contact_uri.len = strlen(contact_uri.s); LM_DBG("Contact: %.*s\n", contact_uri.len, contact_uri.s); /* Add to Usrloc: */ result = process_contact(domain, &ul_record, aor_key, callid, cseq, expires, event, contact_uri); /* Process the result */ if (final_result != RESULT_CONTACTS_FOUND) final_result = result; next_uri: uris = uris->next; } next_contact: contacts = contacts->next; } } next_registration: // if (ul_record) ul.release_urecord(ul_record); /* Unlock the domain for this AOR: */ if (aor_key.len > 0) ul.unlock_udomain(domain, &aor_key); registrations = registrations->next; } error: /* Free the XML-Document */ if(doc) xmlFreeDoc(doc); return final_result; }
int process_body(struct sip_msg* msg, str notify_body, udomain_t * domain) { xmlDocPtr doc = NULL; xmlNodePtr doc_root = NULL, registrations = NULL, contacts = NULL, uris = NULL; str aor = {0, 0}; str callid = {0, 0}; str contact_uri = {0, 0}; str received = {0, 0}; str path = {0, 0}; str user_agent = {0, 0}; int reg_state, contact_state, event, expires, result, final_result = RESULT_ERROR; char * expires_char=0, * cseq_char=0, *registration_state=0, *contact_state_s=0, *event_s=0; int cseq = 0; pv_elem_t *presentity_uri_pv; doc = xmlParseMemory(notify_body.s, notify_body.len); if (doc == NULL) { LM_ERR("Error while parsing the xml body message, Body is:\n%.*s\n", notify_body.len, notify_body.s); return -1; } doc_root = xmlGetNodeByName(doc->children, "reginfo"); if (doc_root == NULL) { LM_ERR("while extracting the reginfo node\n"); goto error; } registrations = doc_root->children; while (registrations) { /* Only process registration sub-items */ if (xmlStrcasecmp(registrations->name, BAD_CAST "registration") != 0) goto next_registration; registration_state = xmlGetAttrContentByName(registrations, "state"); reg_state = reginfo_parse_state(registration_state); if (reg_state == STATE_UNKNOWN) { LM_ERR("No state for this registration!\n"); goto next_registration; } aor.s = xmlGetAttrContentByName(registrations, "aor"); if (aor.s == NULL) { LM_ERR("No AOR for this registration!\n"); goto next_registration; } aor.len = strlen(aor.s); LM_DBG("AOR %.*s has reg_state \"%d\"\n", aor.len, aor.s, reg_state); if (reg_state == STATE_TERMINATED) { //TODO we if there is a IMPU record state here we should delete all contacts associated to it //Right now we do it go through all the contacts LM_DBG("AOR %.*s is in state terminated so unsubscribing from reginfo\n", aor.len, aor.s); //we return a successful result here even if no contacts final_result = RESULT_TERMINATED_SUCCESS; if (pv_parse_format(&aor, &presentity_uri_pv) < 0) { LM_ERR("wrong format[%.*s] - failed unsubscribing to reginfo\n", aor.len, aor.s); } reginfo_subscribe_real(msg, presentity_uri_pv, 0, 0); pv_elem_free_all(presentity_uri_pv); } /* Now lets process the Contact's from this Registration: */ contacts = registrations->children; while (contacts) { if (xmlStrcasecmp(contacts->name, BAD_CAST "contact") != 0) goto next_contact; callid.s = xmlGetAttrContentByName(contacts, "callid"); if (callid.s == NULL) { LM_DBG("No Call-ID for this contact!\n"); callid.len = 0; } else { callid.len = strlen(callid.s); LM_DBG("contact has callid <%.*s>\n", callid.len, callid.s); } received.s = xmlGetAttrContentByName(contacts, "received"); if (received.s == NULL) { LM_DBG("No received for this contact!\n"); received.len = 0; } else { received.len = strlen(received.s); LM_DBG("contact has received <%.*s>\n", received.len, received.s); } path.s = xmlGetAttrContentByName(contacts, "path"); if (path.s == NULL) { LM_DBG("No path for this contact!\n"); path.len = 0; } else { path.len = strlen(path.s); LM_DBG("contact has path <%.*s>\n", path.len, path.s); } user_agent.s = xmlGetAttrContentByName(contacts, "user_agent"); if (user_agent.s == NULL) { LM_DBG("No user_agent for this contact!\n"); user_agent.len = 0; } else { user_agent.len = strlen(user_agent.s); LM_DBG("contact has user_agent <%.*s>\n", user_agent.len, user_agent.s); } event_s = xmlGetAttrContentByName(contacts, "event"); event = reginfo_parse_event(event_s); if (event == EVENT_UNKNOWN) { LM_ERR("No event for this contact - going to next contact!\n"); goto next_contact; } expires_char = xmlGetAttrContentByName(contacts, "expires"); if (expires_char == NULL) { LM_ERR("No expires for this contact - going to next contact!\n"); goto next_contact; } expires = atoi(expires_char); if (expires < 0) { LM_ERR("No valid expires for this contact - going to next contact!\n"); goto next_contact; } contact_state_s = xmlGetAttrContentByName(contacts, "state"); contact_state = reginfo_parse_state(contact_state_s); if (contact_state == STATE_UNKNOWN) { LM_ERR("No state for this contact - going to next contact!\n"); goto next_contact; } LM_DBG("Contact state %d: Event \"%d\", expires %d\n", contact_state, event, expires); cseq_char = xmlGetAttrContentByName(contacts, "cseq"); if (cseq_char == NULL) { LM_DBG("No cseq for this contact!\n"); } else { cseq = atoi(cseq_char); if (cseq < 0) { LM_DBG("No valid cseq for this contact!\n"); } } /* Now lets process the URI's from this Contact: */ uris = contacts->children; while (uris) { if (xmlStrcasecmp(uris->name, BAD_CAST "uri") != 0) goto next_uri; contact_uri.s = (char*) xmlNodeGetContent(uris); if (contact_uri.s == NULL) { LM_ERR("No URI for this contact - going to next registration!\n"); goto next_registration; } contact_uri.len = strlen(contact_uri.s); LM_DBG("Contact: %.*s\n", contact_uri.len, contact_uri.s); /* Add to Usrloc: */ result = process_contact(domain, expires, contact_uri, contact_state); if (contact_uri.s && (strlen(contact_uri.s)>0)) { xmlFree(contact_uri.s); contact_uri.s = NULL; } /* Process the result */ if (final_result != RESULT_CONTACTS_FOUND) final_result = result; next_uri: uris = uris->next; } next_contact: if (cseq_char && (strlen(cseq_char)>0)) { xmlFree(cseq_char); cseq_char=NULL; } if (expires_char && (strlen(expires_char)>0)) { xmlFree(expires_char); expires_char = NULL; } if (user_agent.s && (strlen(user_agent.s)>0)) { xmlFree(user_agent.s); user_agent.s = NULL; } if (path.s && (strlen(path.s)>0)) { xmlFree(path.s); path.s = NULL; } if (received.s && (strlen(received.s)>0)) { xmlFree(received.s); received.s = NULL; } if (callid.s && (strlen(callid.s)>0)) { xmlFree(callid.s); callid.s = NULL; } if (contact_state_s && (strlen(contact_state_s)>0)) { xmlFree(contact_state_s); contact_state_s = NULL; } if (event_s && (strlen(event_s)>0)) { xmlFree(event_s); event_s = NULL; } contacts = contacts->next; } next_registration: // if (ul_record) ul.release_urecord(ul_record); /* Unlock the domain for this AOR: */ //if (aor_key.len > 0) // ul.unlock_udomain(domain, &aor_key); if (registration_state && (strlen(registration_state)>0)) { xmlFree(registration_state); registration_state = NULL; } if (aor.len > 0 && aor.s) { xmlFree(aor.s); aor.s = NULL; aor.len = 0; } registrations = registrations->next; } error: /* Free the XML-Document */ if (doc) xmlFreeDoc(doc); return final_result; }