示例#1
0
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;
}
示例#2
0
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;
}