struct mi_root* mi_pua_subscribe(struct mi_root* cmd, void* param) { int exp= 0; str pres_uri, watcher_uri, expires; struct mi_node* node= NULL; struct mi_root* rpl= NULL; struct sip_uri uri; subs_info_t subs; int sign= 1; str event; node = cmd->node.kids; if(node == NULL) return 0; pres_uri= node->value; if(pres_uri.s == NULL || pres_uri.s== 0) { return init_mi_tree(400, "Bad uri", 7); } if(parse_uri(pres_uri.s, pres_uri.len, &uri)<0 ) { LM_ERR("bad uri\n"); return init_mi_tree(400, "Bad uri", 7); } node = node->next; if(node == NULL) return 0; watcher_uri= node->value; if(watcher_uri.s == NULL || watcher_uri.s== 0) { return init_mi_tree(400, "Bad uri", 7); } if(parse_uri(watcher_uri.s, watcher_uri.len, &uri)<0 ) { LM_ERR("bad uri\n"); return init_mi_tree(400, "Bad uri", 7); } /* Get event */ node = node->next; if(node == NULL) return 0; event= node->value; if(event.s== NULL || event.len== 0) { LM_ERR("empty event parameter\n"); return init_mi_tree(400, "Empty event parameter", 21); } LM_DBG("event '%.*s'\n", event.len, event.s); node = node->next; if(node == NULL || node->next!=NULL) { LM_ERR("Too much or too many parameters\n"); return 0; } expires= node->value; if(expires.s== NULL || expires.len== 0) { LM_ERR("Bad expires parameter\n"); return init_mi_tree(400, "Bad expires", 11); } if(expires.s[0]== '-') { sign= -1; expires.s++; expires.len--; } if( str2int(&expires, (unsigned int*) &exp)< 0) { LM_ERR("invalid expires parameter\n" ); goto error; } exp= exp* sign; LM_DBG("expires '%d'\n", exp); memset(&subs, 0, sizeof(subs_info_t)); subs.pres_uri= &pres_uri; subs.watcher_uri= &watcher_uri; subs.contact= &watcher_uri; subs.expires= exp; subs.source_flag |= MI_SUBSCRIBE; subs.event= get_event_flag(&event); if(subs.event< 0) { LM_ERR("unkown event\n"); return init_mi_tree(400, "Unknown event", 13); } if(pua_send_subscribe(&subs)< 0) { LM_ERR("while sending subscribe\n"); goto error; } rpl= init_mi_tree(202, "accepted", 8); if(rpl == NULL) return 0; return rpl; error: return 0; }
struct mi_root* mi_pua_publish(struct mi_root* cmd, void* param) { int exp; struct mi_node* node= NULL; str pres_uri, expires; str body= {0, 0}; struct sip_uri uri; publ_info_t publ; str event; str content_type; str etag; int result; int sign= 1; LM_DBG("start\n"); node = cmd->node.kids; if(node == NULL) return 0; /* Get presentity URI */ pres_uri = node->value; if(pres_uri.s == NULL || pres_uri.s== 0) { LM_ERR("empty uri\n"); return init_mi_tree(404, "Empty presentity URI", 20); } if(parse_uri(pres_uri.s, pres_uri.len, &uri)<0 ) { LM_ERR("bad uri\n"); return init_mi_tree(404, "Bad presentity URI", 18); } LM_DBG("pres_uri '%.*s'\n", pres_uri.len, pres_uri.s); node = node->next; if(node == NULL) return 0; /* Get expires */ expires= node->value; if(expires.s== NULL || expires.len== 0) { LM_ERR("empty expires parameter\n"); return init_mi_tree(400, "Empty expires parameter", 23); } if(expires.s[0]== '-') { sign= -1; expires.s++; expires.len--; } if( str2int(&expires, (unsigned int*) &exp)< 0) { LM_ERR("invalid expires parameter\n" ); goto error; } exp= exp* sign; LM_DBG("expires '%d'\n", exp); node = node->next; if(node == NULL) return 0; /* Get event */ event= node->value; if(event.s== NULL || event.len== 0) { LM_ERR("empty event parameter\n"); return init_mi_tree(400, "Empty event parameter", 21); } LM_DBG("event '%.*s'\n", event.len, event.s); node = node->next; if(node == NULL) return 0; /* Get content type */ content_type= node->value; if(content_type.s== NULL || content_type.len== 0) { LM_ERR("empty content type\n"); return init_mi_tree(400, "Empty content type parameter", 28); } LM_DBG("content type '%.*s'\n", content_type.len, content_type.s); node = node->next; if(node == NULL) return 0; /* Get etag */ etag= node->value; if(etag.s== NULL || etag.len== 0) { LM_ERR("empty etag parameter\n"); return init_mi_tree(400, "Bad expires", 11); } LM_DBG("etag '%.*s'\n", etag.len, etag.s); node = node->next; /* Get body */ if(node == NULL ) { body.s= NULL; body.len= 0; } else { if(node->next!=NULL) return init_mi_tree(400, "Too many parameters", 19); body= node->value; if(body.s == NULL || body.s== 0) { LM_ERR("empty body parameter\n"); return init_mi_tree(400, "Empty body parameter", 20); } } LM_DBG("body '%.*s'\n", body.len, body.s); /* Check that body is NULL iff content type is . */ if(body.s== NULL && (content_type.len!= 1 || content_type.s[0]!= '.')) { LM_ERR("body is missing, but content type is not .\n"); return init_mi_tree(400, "Body parameter is missing", 25); } /* Create the publ_info_t structure */ memset(&publ, 0, sizeof(publ_info_t)); publ.pres_uri= &pres_uri; if(body.s) { publ.body= &body; } publ.event= get_event_flag(&event); if(publ.event< 0) { LM_ERR("unkown event\n"); return init_mi_tree(400, "Unknown event", 13); } if(content_type.len!= 1) { publ.content_type= content_type; } if(! (etag.len== 1 && etag.s[0]== '.')) { publ.etag= &etag; } publ.expires= exp; if (cmd->async_hdl!=NULL) { publ.source_flag= MI_ASYN_PUBLISH; publ.cb_param= (void*)cmd->async_hdl; } else publ.source_flag|= MI_PUBLISH; LM_DBG("send publish\n"); result= pua_send_publish(&publ); if(result< 0) { LM_ERR("sending publish failed\n"); return init_mi_tree(500, "MI/PUBLISH failed", 17); } if(result== 418) return init_mi_tree(418, "Wrong ETag", 10); if (cmd->async_hdl==NULL) return init_mi_tree( 202, "Accepted", 8); else return MI_ROOT_ASYNC_RPL; error: return 0; }
int rls_handle_notify(struct sip_msg* msg, char* c1, char* c2) { struct to_body *pto, TO = {0}, *pfrom = NULL; str body= {0, 0}; ua_pres_t dialog; str* res_id= NULL; db_key_t query_cols[8]; db_val_t query_vals[8]; int n_query_cols= 0; str auth_state= {0, 0}; int found= 0; str reason = {0, 0}; int auth_flag; struct hdr_field* hdr= NULL; int expires= -1; str content_type= {0, 0}; int reply_code = 500; str reply_str = pu_500_rpl; LM_DBG("start\n"); /* extract the dialog information and check if an existing dialog*/ if( parse_headers(msg,HDR_EOH_F, 0)==-1 ) { LM_ERR("parsing headers\n"); reply_code = 400; reply_str = pu_400_rpl; goto error; } if((!msg->event ) ||(msg->event->body.len<=0)) { LM_ERR("Missing event header field value\n"); reply_code = 400; reply_str = pu_400_rpl; goto error; } if( msg->to==NULL || msg->to->body.s==NULL) { LM_ERR("cannot parse TO header\n"); reply_code = 400; reply_str = pu_400_rpl; goto error; } if(msg->to->parsed != NULL) { pto = (struct to_body*)msg->to->parsed; LM_DBG("'To' header ALREADY PARSED: <%.*s>\n", pto->uri.len, pto->uri.s ); } else { parse_to(msg->to->body.s,msg->to->body.s + msg->to->body.len + 1, &TO); if(TO.uri.len <= 0) { LM_ERR(" 'To' header NOT parsed\n"); reply_code = 400; reply_str = pu_400_rpl; goto error; } pto = &TO; } memset(&dialog, 0, sizeof(ua_pres_t)); dialog.watcher_uri= &pto->uri; if (pto->tag_value.s==NULL || pto->tag_value.len==0 ) { LM_ERR("to tag value not parsed\n"); reply_code = 400; reply_str = pu_400_rpl; goto error; } dialog.from_tag= pto->tag_value; if( msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot parse callid header\n"); reply_code = 400; reply_str = pu_400_rpl; goto error; } dialog.call_id = msg->callid->body; if (!msg->from || !msg->from->body.s) { LM_ERR("cannot find 'from' header!\n"); reply_code = 400; reply_str = pu_400_rpl; goto error; } if (msg->from->parsed == NULL) { LM_DBG("'From' header not parsed\n"); /* parsing from header */ if ( parse_from_header( msg )<0 ) { LM_ERR("cannot parse From header\n"); reply_code = 400; reply_str = pu_400_rpl; goto error; } } pfrom = (struct to_body*)msg->from->parsed; dialog.pres_uri= &pfrom->uri; if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0) { LM_ERR("no from tag value present\n"); reply_code = 400; reply_str = pu_400_rpl; goto error; } dialog.to_tag= pfrom->tag_value; dialog.flag|= RLS_SUBSCRIBE; dialog.event= get_event_flag(&msg->event->body); if(dialog.event< 0) { LM_ERR("unrecognized event package\n"); reply_code = 489; reply_str = pu_489_rpl; goto error; } /* extract the subscription state */ hdr = msg->headers; while (hdr!= NULL) { if(cmp_hdrname_strzn(&hdr->name, "Subscription-State", 18)==0) { found = 1; break; } hdr = hdr->next; } if(found==0 ) { LM_ERR("'Subscription-State' header not found\n"); goto error; } auth_state = hdr->body; /* extract state and reason */ auth_flag= parse_subs_state(auth_state, &reason, &expires); if(auth_flag< 0) { LM_ERR("while parsing 'Subscription-State' header\n"); goto error; } if(pua_get_record_id(&dialog, &res_id)< 0) /* verify if within a stored dialog */ { LM_ERR("occured when trying to get record id\n"); goto error; } if(res_id==0) { LM_DBG("presence dialog record not found\n"); /* if it is a NOTIFY for a terminated SUBSCRIBE dialog in RLS, then * the module might not have the dialog structure anymore * - just send 200ok, it is harmless */ if(auth_flag==TERMINATED_STATE) goto done; LM_INFO("no presence dialog record for non-TERMINATED state uri pres_uri = %.*s watcher_uri = %.*s\n", dialog.pres_uri->len, dialog.pres_uri->s, dialog.watcher_uri->len, dialog.watcher_uri->s); reply_code = 481; reply_str = pu_481_rpl; goto error; } if(msg->content_type== NULL || msg->content_type->body.s== NULL) { LM_DBG("cannot find content type header header\n"); } else content_type= msg->content_type->body; /*constructing the xml body*/ if(get_content_length(msg) == 0 ) { goto done; } else { if(content_type.s== 0) { LM_ERR("content length != 0 and no content type header found\n"); goto error; } body.s=get_body(msg); if (body.s== NULL) { LM_ERR("cannot extract body from msg\n"); goto error; } body.len = get_content_length( msg ); } /* update in rlpres_table where rlsusb_did= res_id and resource_uri= from_uri*/ LM_DBG("body= %.*s\n", body.len, body.s); query_cols[n_query_cols]= &str_rlsubs_did_col; query_vals[n_query_cols].type = DB1_STR; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.str_val= *res_id; n_query_cols++; query_cols[n_query_cols]= &str_resource_uri_col; query_vals[n_query_cols].type = DB1_STR; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.str_val= *dialog.pres_uri; n_query_cols++; query_cols[n_query_cols]= &str_updated_col; query_vals[n_query_cols].type = DB1_INT; query_vals[n_query_cols].nul = 0; if (dbmode == RLS_DB_ONLY) query_vals[n_query_cols].val.int_val= core_hash(res_id, NULL, 0) % (waitn_time * rls_notifier_poll_rate * rls_notifier_processes); else query_vals[n_query_cols].val.int_val = UPDATED_TYPE; n_query_cols++; query_cols[n_query_cols]= &str_auth_state_col; query_vals[n_query_cols].type = DB1_INT; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.int_val= auth_flag; n_query_cols++; query_cols[n_query_cols]= &str_reason_col; query_vals[n_query_cols].type = DB1_STR; query_vals[n_query_cols].nul = 0; if(reason.len > 0) { query_vals[n_query_cols].val.str_val.s= reason.s; query_vals[n_query_cols].val.str_val.len= reason.len; } else { query_vals[n_query_cols].val.str_val.s = ""; query_vals[n_query_cols].val.str_val.len = 0; } n_query_cols++; query_cols[n_query_cols]= &str_content_type_col; query_vals[n_query_cols].type = DB1_STR; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.str_val= content_type; n_query_cols++; query_cols[n_query_cols]= &str_presence_state_col; query_vals[n_query_cols].type = DB1_STR; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.str_val= body; n_query_cols++; query_cols[n_query_cols]= &str_expires_col; query_vals[n_query_cols].type = DB1_INT; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.int_val= expires+ (int)time(NULL); n_query_cols++; if (rlpres_dbf.use_table(rlpres_db, &rlpres_table) < 0) { LM_ERR("in use_table\n"); goto error; } if (dbmode == RLS_DB_ONLY && rlpres_dbf.start_transaction) { if (rlpres_dbf.start_transaction(rlpres_db) < 0) { LM_ERR("in start_transaction\n"); goto error; } } if (rlpres_dbf.replace != NULL) { if(rlpres_dbf.replace(rlpres_db, query_cols, query_vals, n_query_cols, 2, 0)< 0) { LM_ERR("in sql replace\n"); goto error; } LM_DBG("Inserted/replace in database table new record\n"); } else { if(rlpres_dbf.update(rlpres_db, query_cols, 0, query_vals, query_cols+2, query_vals+2, 2, n_query_cols-2)< 0) { LM_ERR("in sql update\n"); goto error; } if (rlpres_dbf.affected_rows(rlpres_db) == 0) { if(rlpres_dbf.insert(rlpres_db, query_cols, query_vals, n_query_cols)< 0) { LM_ERR("in sql insert\n"); goto error; } LM_DBG("Inserted in database table new record\n"); } } if (dbmode == RLS_DB_ONLY && rlpres_dbf.end_transaction) { if (rlpres_dbf.end_transaction(rlpres_db) < 0) { LM_ERR("in end_transaction\n"); goto error; } } LM_DBG("Updated rlpres_table\n"); /* reply 200OK */ done: if(slb.freply(msg, 200, &su_200_rpl) < 0) { LM_ERR("while sending reply\n"); goto error; } if(res_id!=NULL) { pkg_free(res_id->s); pkg_free(res_id); } if (reason.s) pkg_free(reason.s); free_to_params(&TO); return 1; error: if(slb.freply(msg, reply_code, &reply_str) < 0) { LM_ERR("failed sending reply\n"); } if(res_id!=NULL) { pkg_free(res_id->s); pkg_free(res_id); } if (reason.s) pkg_free(reason.s); free_to_params(&TO); if (dbmode == RLS_DB_ONLY && rlpres_dbf.abort_transaction) { if (rlpres_dbf.abort_transaction(rlpres_db) < 0) LM_ERR("in abort_transaction\n"); } return -1; }
int resource_subscriptions(subs_t* subs, xmlNodePtr rl_node) { char* uri= NULL; subs_info_t s; str wuri= {0, 0}; str did_str= {0, 0}; str *tmp_str; int cont_no= 0; static str ehdr= {SUBS_EXTRA_HDRS, SUBS_EXTRA_HDRS_LEN}; list_entry_t *rls_contact_list = NULL; list_entry_t *rls_subs_list = NULL; void* params[2] = {&s, &rls_contact_list}; /* if is initial send an initial Subscribe * else search in hash table for a previous subscription */ if(CONSTR_RLSUBS_DID(subs, &did_str)< 0) { LM_ERR("Failed to create did\n"); return -1; } memset(&s, 0, sizeof(subs_info_t)); if( uandd_to_uri(subs->from_user, subs->from_domain, &wuri)< 0) { LM_ERR("while constructing uri from user and domain\n"); goto error; } s.id= did_str; s.watcher_uri= &wuri; s.to_uri.s=0; s.contact= &server_address; s.event= get_event_flag(&subs->event->name); if(presence_server.s) s.outbound_proxy= &presence_server; if(s.event< 0) { LM_ERR("not recognized event\n"); goto error; } s.expires= subs->expires; s.source_flag= RLS_SUBSCRIBE; s.extra_headers= &ehdr; s.internal_update_flag = subs->internal_update_flag; if(process_list_and_exec(rl_node, subs->from_user, subs->from_domain, send_resource_subs, params, &cont_no) < 0) { LM_ERR("while processing list\n"); goto error; } LM_INFO("Subscription from %.*s for resource list uri %.*s expanded to" " %d contacts\n", wuri.len, wuri.s, subs->pres_uri.len, subs->pres_uri.s, cont_no); if (s.internal_update_flag) { s.internal_update_flag = 0; rls_subs_list = pua_get_subs_list(&did_str); while ((tmp_str = list_pop(&rls_contact_list)) != NULL) { rls_subs_list = list_remove(*tmp_str, rls_subs_list); pkg_free(tmp_str->s); pkg_free(tmp_str); } while ((tmp_str = list_pop(&rls_subs_list)) != NULL) { LM_DBG("Removing subscription for %.*s\n", tmp_str->len, tmp_str->s); s.expires = 0; send_resource_subs(tmp_str->s, params); pkg_free(tmp_str->s); pkg_free(tmp_str); } } if (rls_contact_list != NULL) { list_free(&rls_contact_list); } pkg_free(wuri.s); pkg_free(did_str.s); return 0; error: if(wuri.s) pkg_free(wuri.s); if(uri) xmlFree(uri); if(did_str.s) pkg_free(did_str.s); return -1; }
/** * send subscriptions to the list from XML node */ int resource_subscriptions(subs_t* subs, xmlNodePtr xmlnode) { subs_info_t s; str wuri= {0, 0}; str extra_headers; str did_str= {0, 0}; str *tmp_str; list_entry_t *rls_contact_list = NULL; list_entry_t *rls_subs_list = NULL; void* params[2] = {&s, &rls_contact_list}; /* if is initial send an initial Subscribe * else search in hash table for a previous subscription */ if(CONSTR_RLSUBS_DID(subs, &did_str)<0) { LM_ERR("cannot build rls subs did\n"); goto error; } memset(&s, 0, sizeof(subs_info_t)); if(uandd_to_uri(subs->watcher_user, subs->watcher_domain, &wuri)<0) { LM_ERR("while constructing uri from user and domain\n"); goto error; } s.id = did_str; s.watcher_uri = &wuri; s.contact = &rls_server_address; s.event = get_event_flag(&subs->event->name); if(s.event<0) { LM_ERR("not recognized event\n"); goto error; } s.expires = subs->expires; s.source_flag = RLS_SUBSCRIBE; if(rls_outbound_proxy.s) s.outbound_proxy = &rls_outbound_proxy; extra_headers.s = "Supported: eventlist\r\n" "Accept: application/pidf+xml, application/rlmi+xml," " application/watcherinfo+xml," " multipart/related\r\n"; extra_headers.len = strlen(extra_headers.s); s.extra_headers = &extra_headers; s.internal_update_flag = subs->internal_update_flag; counter = 0; if(process_list_and_exec(xmlnode, subs->watcher_user, subs->watcher_domain, send_resource_subs, params)<0) { LM_ERR("while processing list\n"); goto error; } if (rls_max_backend_subs > 0 && counter > rls_max_backend_subs) LM_WARN("%.*s has too many contacts. Max: %d, has: %d\n", wuri.len, wuri.s, rls_max_backend_subs, counter); if (s.internal_update_flag == INTERNAL_UPDATE_TRUE) { counter = 0; s.internal_update_flag = 0; rls_subs_list = pua_get_subs_list(&did_str); while ((tmp_str = list_pop(&rls_contact_list)) != NULL) { LM_DBG("Finding and removing %.*s from subscription list\n", tmp_str->len, tmp_str->s); rls_subs_list = list_remove(*tmp_str, rls_subs_list); pkg_free(tmp_str->s); pkg_free(tmp_str); } while ((tmp_str = list_pop(&rls_subs_list)) != NULL) { LM_DBG("Removing subscription for %.*s\n", tmp_str->len, tmp_str->s); s.expires = 0; send_resource_subs(tmp_str->s, params); pkg_free(tmp_str->s); pkg_free(tmp_str); } } if (rls_contact_list != NULL) list_free(&rls_contact_list); pkg_free(wuri.s); pkg_free(did_str.s); return 0; error: if(wuri.s) pkg_free(wuri.s); if(did_str.s) pkg_free(did_str.s); if(rls_contact_list) list_free(&rls_contact_list); return -1; }
static void pua_rpc_publish(rpc_t* rpc, void* c) { str pres_uri, expires, event, content_type, id, etag, outbound_proxy, extra_headers, body; rpc_delayed_ctx_t* dctx; int exp, sign, ret, err_ret, sip_error; char err_buf[MAX_REASON_LEN]; struct sip_uri uri; publ_info_t publ; body.s = 0; body.len = 0; dctx = 0; LM_DBG("rpc publishing ...\n"); if ((rpc->capabilities == 0) || !(rpc->capabilities(c) & RPC_DELAYED_REPLY)) { rpc->fault(c, 600, "Reply wait/async mode not supported" " by this rpc transport"); return; } ret = rpc->scan(c, "SSSSSSSS*S", &pres_uri, &expires, &event, &content_type, &id, &etag, &outbound_proxy, &extra_headers, &body); if (ret < 8) { rpc->fault(c, 400, "Too few or wrong type of parameters (%d)", ret); return; } if (parse_uri(pres_uri.s, pres_uri.len, &uri) <0) { LM_ERR("bad resentity uri\n"); rpc->fault(c, 400, "Invalid presentity uri '%s'", pres_uri.s); return; } LM_DBG("presentity uri '%.*s'\n", pres_uri.len, pres_uri.s); if (expires.s[0]== '-') { sign= -1; expires.s++; expires.len--; } else { sign = 1; } if (str2int(&expires, (unsigned int*)&exp) < 0) { LM_ERR("invalid expires parameter\n" ); rpc->fault(c, 400, "Invalid expires value '%s'", expires.s); return; } exp = exp * sign; LM_DBG("expires '%d'\n", exp); LM_DBG("event '%.*s'\n", event.len, event.s); LM_DBG("content type '%.*s'\n", content_type.len, content_type.s); LM_DBG("id '%.*s'\n", id.len, id.s); LM_DBG("ETag '%.*s'\n", etag.len, etag.s); LM_DBG("outbound_proxy '%.*s'\n", outbound_proxy.len, outbound_proxy.s); LM_DBG("extra headers '%.*s'\n", extra_headers.len, extra_headers.s); if (body.len > 0) LM_DBG("body '%.*s'\n", body.len, body.s); if ((body.s == 0) && (content_type.len != 1 || content_type.s[0] != '.')) { LM_ERR("body is missing, but content type is not .\n"); rpc->fault(c, 400, "Body is missing"); return; } memset(&publ, 0, sizeof(publ_info_t)); publ.pres_uri= &pres_uri; publ.expires= exp; publ.event= get_event_flag(&event); if (publ.event < 0) { LM_ERR("unknown event '%.*s'\n", event.len, event.s); rpc->fault(c, 400, "Unknown event"); return; } if (content_type.len != 1) { publ.content_type= content_type; } if (!((id.len == 1) && (id.s[0]== '.'))) { publ.id= id; } if (!((etag.len== 1) && (etag.s[0]== '.'))) { publ.etag= &etag; } if (!((outbound_proxy.len == 1) && (outbound_proxy.s[0] == '.'))) { publ.outbound_proxy = &outbound_proxy; } if (!((extra_headers.len == 1) && (extra_headers.s[0] == '.'))) { publ.extra_headers = &extra_headers; } if (body.s != 0) { publ.body= &body; } dctx = rpc->delayed_ctx_new(c); if (dctx == 0) { LM_ERR("internal error: failed to create context\n"); rpc->fault(c, 500, "Internal error: failed to create context"); return; } publ.cb_param = dctx; publ.source_flag = MI_ASYN_PUBLISH; ret = pua_rpc_api.send_publish(&publ); LM_DBG("pua send_publish returned %d\n", ret); if (dctx->reply_ctx != 0) { /* callback was not executed or its execution failed */ rpc = &dctx->rpc; c = dctx->reply_ctx; } else { return; } if (ret < 0) { LM_ERR("pua send_publish failed\n"); err_ret = err2reason_phrase(ret, &sip_error, err_buf, sizeof(err_buf), "RPC/PUBLISH") ; if (err_ret > 0 ) { rpc->fault(c, sip_error, "%s", err_buf); } else { rpc->fault(c, 500, "RPC/PUBLISH error"); } rpc->delayed_ctx_close(dctx); } if (ret == 418) { rpc->fault(c, 500, "Wrong ETag"); rpc->delayed_ctx_close(dctx); } return; }
int rls_handle_notify(struct sip_msg* msg, char* c1, char* c2) { struct to_body *pto, *pfrom= NULL; str body= {0, 0}; ua_pres_t dialog; str* res_id= NULL; db_key_t query_cols[9], result_cols[1]; db_val_t query_vals[9]; db_res_t* result= NULL; int n_query_cols= 0; str auth_state= {0, 0}; str* reason= NULL; int auth_flag; struct hdr_field* hdr= NULL; int n, expires= -1; str ctype= {0, 0}; int err_ret = -1; LM_DBG("start\n"); /* extract the dialog information and check if an existing dialog*/ if( parse_headers(msg,HDR_EOH_F, 0)==-1 ) { LM_ERR("parsing headers\n"); return -1; } if((!msg->event ) ||(msg->event->body.len<=0)) { LM_ERR("Missing event header field value\n"); return -1; } if( msg->to==NULL || msg->to->body.s==NULL) { LM_ERR("cannot parse TO header\n"); return -1; } pto = get_to(msg); if (pto == NULL || pto->error != PARSE_OK) { LM_ERR("failed to parse TO header\n"); return -1; } memset(&dialog, 0, sizeof(ua_pres_t)); dialog.watcher_uri= &pto->uri; if (pto->tag_value.s==NULL || pto->tag_value.len==0 ) { LM_ERR("to tag value not parsed\n"); goto error; } dialog.from_tag= pto->tag_value; if( msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot parse callid header\n"); goto error; } dialog.call_id = msg->callid->body; if (!msg->from || !msg->from->body.s) { LM_ERR("cannot find 'from' header!\n"); goto error; } if (msg->from->parsed == NULL) { LM_DBG("'From' header not parsed\n"); /* parsing from header */ if ( parse_from_header( msg )<0 ) { LM_ERR("cannot parse From header\n"); goto error; } } pfrom = (struct to_body*)msg->from->parsed; dialog.pres_uri= &pfrom->uri; if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0) { LM_ERR("no from tag value present\n"); goto error; } dialog.to_tag= pfrom->tag_value; dialog.flag|= RLS_SUBSCRIBE; dialog.event= get_event_flag(&msg->event->body); if(dialog.event< 0) { LM_ERR("unrecognized event package\n"); goto error; } if(pua_get_record_id(&dialog, &res_id)< 0) // verify if within a stored dialog { LM_ERR("error occured while trying to get dialog record id\n"); goto error; } if(res_id== 0) { LM_DBG("no dialog match found in hash table\n"); err_ret = 2; goto error; } /* extract the subscription state */ hdr = get_header_by_static_name( msg, "Subscription-State"); if( hdr==NULL ) { LM_ERR("'Subscription-State' header not found\n"); goto error; } auth_state = hdr->body; /* extract state and reason */ auth_flag= parse_subs_state(auth_state, &reason, &expires); if(auth_flag< 0) { LM_ERR("while parsing 'Subscription-State' header\n"); goto error; } if(msg->content_type== NULL || msg->content_type->body.s== NULL) { LM_DBG("cannot find content type header\n"); } else ctype= msg->content_type->body; LM_DBG("NOTIFY for [user]= %.*s\n",dialog.pres_uri->len, dialog.pres_uri->s); /*constructing the xml body*/ if(get_content_length(msg) == 0 ) { LM_DBG("null body\n"); goto done; } else { if(ctype.s== 0) { LM_ERR("content length != 0 and no content type header found\n"); goto error; } if ( get_body(msg,&body)!=0 || body.len==0) { LM_ERR("cannot extract body from msg\n"); goto error; } LM_DBG("[body]= %.*s\n", body.len, body.s); } /* update in rlpres_table where rlsusb_did= res_id and resource_uri= from_uri*/ query_cols[n_query_cols]= &str_rlsubs_did_col; query_vals[n_query_cols].type = DB_STR; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.str_val= *res_id; n_query_cols++; query_cols[n_query_cols]= &str_resource_uri_col; query_vals[n_query_cols].type = DB_STR; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.str_val= *dialog.pres_uri; n_query_cols++; query_cols[n_query_cols]= &str_updated_col; query_vals[n_query_cols].type = DB_INT; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.int_val= UPDATED_TYPE; n_query_cols++; query_cols[n_query_cols]= &str_auth_state_col; query_vals[n_query_cols].type = DB_INT; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.int_val= auth_flag; n_query_cols++; if(reason) { query_cols[n_query_cols]= &str_reason_col; query_vals[n_query_cols].type = DB_STR; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.str_val= *reason; n_query_cols++; } query_cols[n_query_cols]= &str_content_type_col; query_vals[n_query_cols].type = DB_STR; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.str_val= ctype; n_query_cols++; query_cols[n_query_cols]= &str_presence_state_col; query_vals[n_query_cols].type = DB_STR; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.str_val= body; n_query_cols++; query_cols[n_query_cols]= &str_expires_col; query_vals[n_query_cols].type = DB_INT; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.int_val= expires+ (int)time(NULL); n_query_cols++; if (rls_dbf.use_table(rls_db, &rlpres_table) < 0) { LM_ERR("in use_table\n"); goto error; } /* query-> if not present insert // else update */ result_cols[0]= &str_updated_col; if(rls_dbf.query(rls_db, query_cols, 0, query_vals, result_cols, 2, 1, 0, &result)< 0) { LM_ERR("in sql query\n"); if(result) rls_dbf.free_result(rls_db, result); goto error; } if(result== NULL) goto error; n= result->n; rls_dbf.free_result(rls_db, result); if(n<= 0) { if(rls_dbf.insert(rls_db, query_cols, query_vals, n_query_cols)< 0) { LM_ERR("in sql insert\n"); goto error; } } else { if(expires!= 0) { if(rls_dbf.update(rls_db, query_cols, 0, query_vals, query_cols+2, query_vals+2, 2, n_query_cols-2)< 0) { LM_ERR("in sql update\n"); goto error; } } else /* if terminated - delete from rls_presentity table */ { if(rls_dbf.delete(rls_db, query_cols, 0, query_vals, 2)< 0) { LM_ERR("sql delete failed\n"); goto error; } } } done: if( rls_sigb.reply(msg, 200, &su_200_rpl, 0) < 0) { LM_ERR("failed to send SIP reply\n"); goto error; } pkg_free(res_id->s); pkg_free(res_id); return 1; error: if(res_id) { pkg_free(res_id->s); pkg_free(res_id); } return err_ret; }