static int w_sdp_content_sloppy(sip_msg_t* msg, char* foo, char *bar) { str body; int mime; body.s = get_body(msg); if (body.s == NULL) return -1; body.len = msg->len - (int)(body.s - msg->buf); if (body.len == 0) return -1; mime = parse_content_type_hdr(msg); if (mime < 0) return -1; /* error */ if (mime == 0) return 1; /* default is application/sdp */ switch (((unsigned int)mime) >> 16) { case TYPE_APPLICATION: if ((mime & 0x00ff) == SUBTYPE_SDP) return 1; else return -1; case TYPE_MULTIPART: if ((mime & 0x00ff) == SUBTYPE_MIXED) { if (_strnistr(body.s, "application/sdp", body.len) == NULL) { return -1; } else { return 1; } } else { return -1; } default: return -1; } }
/** * Updates the registrar with the new values * @param req - the REGISTER request - to extract NAT info * @param rpl - the REGISTER reply - to extract contact info * @param is_star - whether this was a STAR contact header * @param expires_hdr - value of the Expires header * @param public_id - array of public identities attached to this contact * @param public_id_cnt - size of the public_id array * @param service_route - array of Service-Routes * @param service_route_cnt - size of the service_route array * @param requires_nat - if to create pinholes * @returns the maximum expiration time, -1 on error */ static inline int update_contacts(struct sip_msg *req,struct sip_msg *rpl, udomain_t* _d, unsigned char is_star,int expires_hdr, str *public_id,int public_id_cnt,str *service_route,int service_route_cnt, int requires_nat) { int local_time_now, expires=0; struct hdr_field* h; contact_t* c; struct sip_uri puri; struct pcontact_info ci; pcontact_t* pcontact; unsigned short port, proto; char *alias_start, *p, *port_s, *proto_s; char portbuf[5]; str alias_s; pcscf_act_time(); local_time_now = time_now; if (is_star) { /* first of all, we shouldn't get here... * then, we will update on NOTIFY */ return 0; } // Set the structure to "0", to make sure it's properly initialized memset(&ci, 0, sizeof(struct pcontact_info)); for (h = rpl->contact; h; h = h->next) { if (h->type == HDR_CONTACT_T && h->parsed) { for (c = ((contact_body_t*) h->parsed)->contacts; c; c = c->next) { expires = calc_contact_expires(c, expires_hdr, local_time_now); if (parse_uri(c->uri.s, c->uri.len, &puri) < 0) { LM_DBG("Error parsing Contact URI <%.*s>\n", c->uri.len, c->uri.s); continue; } //build contact info ci.aor = c->uri; ci.expires = expires; ci.public_ids = public_id; ci.num_public_ids = public_id_cnt; ci.service_routes = service_route; ci.num_service_routes = service_route_cnt; ci.reg_state = PCONTACT_REGISTERED|PCONTACT_REG_PENDING|PCONTACT_REG_PENDING_AAR; //we don't want to add contacts that did not come through us (pcscf) ci.received_host.len = 0; ci.received_host.s = 0; ci.received_port = 0; ci.received_proto = 0; port = puri.port_no ? puri.port_no : 5060; ci.via_host = puri.host; ci.via_port = port; ci.via_prot = puri.proto; ci.searchflag = SEARCH_NORMAL; /* this must be reset for each contact iteration */ if (puri.params.len > 6 && (alias_start = _strnistr(puri.params.s, "alias=", puri.params.len)) != NULL) { LM_DBG("contact has an alias [%.*s] - we can use that as the received\n", puri.params.len, puri.params.s); alias_s.len = puri.params.len - (alias_start - puri.params.s) - 6; alias_s.s = alias_start + 6; LM_DBG("alias [%.*s]\n", alias_s.len, alias_s.s); p = _strnistr(alias_s.s, "~", alias_s.len); if (p!=NULL) { ci.received_host.s = alias_s.s; ci.received_host.len = p - alias_s.s; LM_DBG("alias(host) [%.*s]\n", ci.received_host.len, ci.received_host.s); port_s = p+1; p = _strnistr(port_s, "~", alias_s.len - ci.received_host.len); if (p!=NULL) { LM_DBG("alias(port) [%.*s]\n", (int)(p - port_s) , port_s); memset(portbuf, 0, 5); memcpy(portbuf, port_s, (p-port_s)); port = atoi(portbuf); LM_DBG("alias(port) [%d]\n", port); proto_s = p + 1; memset(portbuf, 0, 5); memcpy(portbuf, proto_s, 1); proto = atoi(portbuf); LM_DBG("alias(proto) [%d]\n", proto); ci.received_port = port; ci.received_proto = proto; ci.searchflag = SEARCH_RECEIVED; } } } ul.lock_udomain(_d, &puri.host, port, puri.proto); if (ul.get_pcontact(_d, &ci, &pcontact) != 0) { //need to insert new contact if ((expires-local_time_now)<=0) { //remove contact - de-register LM_DBG("This is a de-registration for contact <%.*s> but contact is not in usrloc - ignore\n", c->uri.len, c->uri.s); goto next_contact; } LM_DBG("We don't add contact from the 200OK that did not go through us (ie, not present in explicit REGISTER that went through us\n"); // LM_DBG("Adding pcontact: <%.*s>, expires: %d which is in %d seconds\n", c->uri.len, c->uri.s, expires, expires-local_time_now); // ci.reg_state = PCONTACT_REGISTERED; // if (ul.insert_pcontact(_d, &c->uri, &ci, &pcontact) != 0) { // LM_ERR("Failed inserting new pcontact\n"); // } else { // //register for callbacks on this contact so we can send PUBLISH to SCSCF should status change // LM_DBG("registering for UL callback\n"); // ul.register_ulcb(pcontact, PCSCF_CONTACT_DELETE | PCSCF_CONTACT_EXPIRE, callback_pcscf_contact_cb, NULL); // //we also need to subscribe to reg event of this contact at SCSCF // } } else { //contact already exists - update LM_DBG("contact already exists and is in state (%d) : [%s]\n",pcontact->reg_state, reg_state_to_string(pcontact->reg_state)); if ((expires-local_time_now)<=0) { //remove contact - de-register LM_DBG("This is a de-registration for contact <%.*s>\n", c->uri.len, c->uri.s); if (ul.delete_pcontact(_d, pcontact) != 0) { LM_ERR("failed to delete pcscf contact <%.*s>\n", c->uri.len, c->uri.s); } //TODO_LATEST replace above } else { //update contact LM_DBG("Updating contact: <%.*s>, old expires: %li, new expires: %i which is in %i seconds\n", c->uri.len, c->uri.s, pcontact->expires-local_time_now, expires, expires-local_time_now); ci.reg_state = PCONTACT_REGISTERED; if (ul.update_pcontact(_d, &ci, pcontact) != 0) { LM_ERR("failed to update pcscf contact\n"); } pcontact->expires = expires; } } next_contact: ul.unlock_udomain(_d, &puri.host, port, puri.proto); } } } return 1; }