static inline str* extract_mangled_fromuri(str *mangled_from_hdr) { struct to_body from_b; struct hdr_field hdr; char *tmp,*end; if (mangled_from_hdr->len == 0 || mangled_from_hdr->s == NULL) return NULL; end = mangled_from_hdr->s+mangled_from_hdr->len; tmp=parse_hname2(mangled_from_hdr->s,end,&hdr); if (hdr.type==HDR_ERROR_T) { LM_ERR("bad from header\n"); return NULL; } tmp=eat_lws_end(tmp, end); if (tmp >= end) { LM_ERR("empty header\n"); return NULL; } parse_to(tmp,end,&from_b); if (from_b.error == PARSE_ERROR) { LM_ERR("bad from header [%.*s]\n",mangled_from_hdr->len,mangled_from_hdr->s); return NULL; } extracted_from_uri = from_b.uri; free_to_params(&from_b); LM_DBG("extracted from uri [%.*s]\n",extracted_from_uri.len,extracted_from_uri.s); return &extracted_from_uri; }
struct to_body* get_b2bl_from(struct sip_msg* msg) { int len = 0; if(b2bl_from_spec_param.s) { memset(&b2bl_from_tok, 0, sizeof(pv_value_t)); if(pv_get_spec_value(msg, &b2bl_from_spec, &b2bl_from_tok) < 0) { LM_ERR("Failed to get b2bl_from value\n"); return NULL; } //LM_DBG("got b2bl_from_spec_param flags [%d]\n", b2bl_from_tok.flags); if(b2bl_from_tok.flags&PV_VAL_INT) { /* the PV might be empty */ return NULL; } if(b2bl_from_tok.flags&PV_VAL_STR) { //LM_DBG("got PV_SPEC b2bl_from [%.*s]\n", // b2bl_from_tok.rs.len, b2bl_from_tok.rs.s); if(b2bl_from_tok.rs.len+CRLF_LEN > B2BL_FROM_BUF_LEN) { LM_ERR("Buffer overflow\n"); return NULL; } trim(&b2bl_from_tok.rs); memcpy(b2bl_from_buf, b2bl_from_tok.rs.s, b2bl_from_tok.rs.len); len = b2bl_from_tok.rs.len; if(strncmp(b2bl_from_tok.rs.s + len - CRLF_LEN, CRLF, CRLF_LEN)) { memcpy(b2bl_from_buf + len, CRLF, CRLF_LEN); len+= CRLF_LEN; } parse_to(b2bl_from_buf, b2bl_from_buf+len, &b2bl_from); if (b2bl_from.error != PARSE_OK) { LM_ERR("Failed to parse PV_SPEC b2bl_from [%.*s]\n", len, b2bl_from_buf); return NULL; } if (parse_uri(b2bl_from.uri.s, b2bl_from.uri.len, &b2bl_from.parsed_uri)<0) { LM_ERR("failed to parse PV_SPEC b2bl_from uri [%.*s]\n", b2bl_from.uri.len, b2bl_from.uri.s); return NULL; } /* side effect of parsing - nobody should need them later on, * so free them right now */ free_to_params(&b2bl_from); return &b2bl_from; } } return NULL; }
/* * Get user part from P-Charge-Info header * param msg SIP message * param user User part of P-Charge-Info header * param bufsize Size of fromuser buffer * return 0 success, 1 without P-Charge-Info, -1 failure */ int ospGetPChargeInfoUserpart( struct sip_msg* msg, char* pciuser, int bufsize) { static const char* header = "P-Charge-Info"; struct to_body body; struct to_body* pci=NULL; struct hdr_field *hf; struct sip_uri uri; int result = -1; if ((pciuser != NULL) && (bufsize > 0)) { pciuser[0] = '\0'; if (parse_headers(msg, HDR_EOH_F, 0) < 0) { LM_ERR("failed to parse message\n"); return -1; } for (hf = msg->headers; hf; hf = hf->next) { if ((hf->type == HDR_OTHER_T) && (hf->name.len == strlen(header)) && (strncasecmp(hf->name.s, header, hf->name.len) == 0)) { if (!(pci = hf->parsed)) { pci = &body; parse_to(hf->body.s, hf->body.s + hf->body.len + 1, pci); } if (pci->error != PARSE_ERROR) { if (parse_uri(pci->uri.s, pci->uri.len, &uri) == 0) { ospCopyStrToBuffer(&uri.user, pciuser, bufsize); ospSkipUserParam(pciuser); result = 0; } else { LM_ERR("failed to parse P-Charge-Info uri\n"); } if (pci == &body) { free_to_params(pci); } } else { LM_ERR("bad P-Charge-Info header\n"); } break; } } if (!hf) { LM_DBG("without P-Charge-Info header\n"); result = 1; } } else { LM_ERR("bad parameters to parse user part from PAI\n"); } return result; }
void subs_cback_func(struct cell *t, int cb_type, struct tmcb_params *ps) { struct sip_msg* msg= NULL; int lexpire= 0; unsigned int cseq; ua_pres_t* presentity= NULL, *hentity= NULL; struct to_body *pto = NULL, TO = {0}, *pfrom = NULL; int size= 0; unsigned int hash_code; int flag ; str record_route= {0, 0}; int rt; str contact; int initial_request = 0; int end_transaction = 1; if( ps->param== NULL || *ps->param== NULL ) { LM_ERR("null callback parameter\n"); return; } if (dbmode == PUA_DB_ONLY && pua_dbf.start_transaction) { if (pua_dbf.start_transaction(pua_db, db_table_lock) < 0) { LM_ERR("in start_transaction\n"); goto error; } } LM_DBG("completed with status %d\n",ps->code) ; hentity= (ua_pres_t*)(*ps->param); hash_code= core_hash(hentity->pres_uri,hentity->watcher_uri, HASH_SIZE); flag= hentity->flag; if(hentity->flag & XMPP_INITIAL_SUBS) hentity->flag= XMPP_SUBSCRIBE; /* get dialog information from reply message: callid, to_tag, from_tag */ msg= ps->rpl; if(msg == NULL) { LM_ERR("no reply message found\n "); goto error; } if(msg== FAKED_REPLY) { struct hdr_field *callid = NULL, *from = NULL; struct to_body FROM = {0}; callid = (struct hdr_field *) pkg_malloc(sizeof(struct hdr_field)); if (callid == NULL) { LM_ERR("Out of memory\n"); goto faked_error; } memset(callid, 0, sizeof(struct hdr_field)); get_hdr_field(t->callid.s, t->callid.s + t->callid.len, callid); hentity->call_id = callid->body; from = (struct hdr_field *) pkg_malloc(sizeof(struct hdr_field)); if (from == NULL) { LM_ERR("Out of memory\n"); goto faked_error; } memset(from, 0, sizeof(struct hdr_field)); get_hdr_field(t->from.s, t->from.s + t->from.len, from); parse_to(from->body.s, from->body.s + from->body.len + 1, &FROM); if(FROM.uri.len <= 0) { LM_ERR("'From' header NOT parsed\n"); goto faked_error; } hentity->call_id = callid->body; hentity->from_tag = (&FROM)->tag_value; hentity->to_tag.s = NULL; hentity->to_tag.len = 0; find_and_delete_dialog(hentity, hash_code); faked_error: if (callid) pkg_free(callid); free_to_params(&FROM); if (from) pkg_free(from); goto done; } if ( parse_headers(msg,HDR_EOH_F, 0)==-1 ) { LM_ERR("when parsing headers\n"); goto error; } if(ps->rpl->expires && msg->expires->body.len > 0) { if (!msg->expires->parsed && (parse_expires(msg->expires) < 0)) { LM_ERR("cannot parse Expires header\n"); goto error; } lexpire = ((exp_body_t*)msg->expires->parsed)->val; LM_DBG("lexpire= %d\n", lexpire); } /*if initial request */ if(hentity->call_id.s== NULL) { initial_request = 1; if( msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot parse callid header\n"); goto error; } if (!msg->from || !msg->from->body.s) { LM_ERR("cannot find 'from' header!\n"); goto error; } if (msg->from->parsed == NULL) { if ( parse_from_header( msg )<0 ) { LM_ERR("cannot parse From header\n"); goto error; } } pfrom = (struct to_body*)msg->from->parsed; if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0) { LM_ERR("no from tag value present\n"); goto error; } hentity->call_id= msg->callid->body; hentity->from_tag= pfrom->tag_value; if(ps->code >= 300 || lexpire == 0) { hentity->to_tag.s = NULL; hentity->to_tag.len = 0; find_and_delete_dialog(hentity, hash_code); goto done; } if( msg->to==NULL || msg->to->body.s==NULL) { LM_ERR("cannot parse TO header\n"); 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"); goto error; } pto = &TO; } if( pto->tag_value.s ==NULL || pto->tag_value.len == 0) { LM_ERR("no to tag value present\n"); goto error; } hentity->to_tag= pto->tag_value; } if(ps->code >= 300 ) { /* if an error code and a stored dialog delete it and try to send a subscription with type= INSERT_TYPE, else return*/ subs_info_t subs; hentity->to_tag.s = NULL; hentity->to_tag.len = 0; find_and_delete_dialog(hentity, hash_code); if (dbmode == PUA_DB_ONLY && pua_dbf.end_transaction) { if (pua_dbf.end_transaction(pua_db) < 0) { LM_ERR("in end_transaction\n"); goto error; } } end_transaction = 0; /* Redirect if the response 3XX */ memset(&subs, 0, sizeof(subs_info_t)); subs.pres_uri= hentity->pres_uri; subs.watcher_uri= hentity->watcher_uri; subs.contact= &hentity->contact; if(hentity->remote_contact.s) subs.remote_target= &hentity->remote_contact; if(hentity->desired_expires== 0) subs.expires= -1; else if(hentity->desired_expires< (int)time(NULL)) subs.expires= 0; else subs.expires= hentity->desired_expires- (int)time(NULL)+ 3; subs.flag= INSERT_TYPE; subs.source_flag= flag; subs.event= hentity->event; subs.id= hentity->id; subs.outbound_proxy= hentity->outbound_proxy; subs.extra_headers= hentity->extra_headers; subs.cb_param= hentity->cb_param; if(send_subscribe(&subs)< 0) { LM_ERR("when trying to send SUBSCRIBE\n"); goto error; } goto done; } if(lexpire== 0 ) { LM_DBG("lexpire= 0 Delete from hash table"); find_and_delete_dialog(hentity, hash_code); goto done; } /* extract the contact */ if(msg->contact== NULL || msg->contact->body.s== NULL) { LM_ERR("no contact header found"); goto error; } if( parse_contact(msg->contact) <0 ) { LM_ERR(" cannot parse contact header\n"); goto error; } if(msg->contact->parsed == NULL) { LM_ERR("cannot parse contact header\n"); goto error; } contact = ((contact_body_t* )msg->contact->parsed)->contacts->uri; if( msg->cseq==NULL || msg->cseq->body.s==NULL) { LM_ERR("cannot parse cseq header\n"); goto error; } if( str2int( &(get_cseq(msg)->number), &cseq)< 0) { LM_ERR("while converting str to int\n"); goto error; } if(initial_request == 0) { hentity->cseq = cseq; find_and_update_dialog(hentity, hash_code, lexpire, &contact); goto done; } /*process record route and add it to a string*/ if (msg->record_route!=NULL) { rt = print_rr_body(msg->record_route, &record_route, 1, 0); if(rt != 0) { LM_ERR("parsing record route [%d]\n", rt); record_route.s=NULL; record_route.len=0; } } size= sizeof(ua_pres_t)+ 2*sizeof(str)+( pto->uri.len+ pfrom->uri.len+ pto->tag_value.len+ pfrom->tag_value.len +msg->callid->body.len+ record_route.len+ hentity->contact.len+ hentity->id.len )*sizeof(char); if(hentity->extra_headers) size+= sizeof(str)+ hentity->extra_headers->len*sizeof(char); presentity= (ua_pres_t*)shm_malloc(size); if(presentity== NULL) { LM_ERR("no more share memory\n"); goto error; } memset(presentity, 0, size); size= sizeof(ua_pres_t); presentity->pres_uri= (str*)( (char*)presentity+ size); size+= sizeof(str); presentity->pres_uri->s= (char*)presentity+ size; memcpy(presentity->pres_uri->s, pto->uri.s, pto->uri.len); presentity->pres_uri->len= pto->uri.len; size+= pto->uri.len; presentity->watcher_uri= (str*)( (char*)presentity+ size); size+= sizeof(str); presentity->watcher_uri->s= (char*)presentity+ size; memcpy(presentity->watcher_uri->s, pfrom->uri.s, pfrom->uri.len); presentity->watcher_uri->len= pfrom->uri.len; size+= pfrom->uri.len; presentity->call_id.s= (char*)presentity + size; memcpy(presentity->call_id.s,msg->callid->body.s, msg->callid->body.len); presentity->call_id.len= msg->callid->body.len; size+= presentity->call_id.len; presentity->to_tag.s= (char*)presentity + size; memcpy(presentity->to_tag.s,pto->tag_value.s, pto->tag_value.len); presentity->to_tag.len= pto->tag_value.len; size+= pto->tag_value.len; presentity->from_tag.s= (char*)presentity + size; memcpy(presentity->from_tag.s,pfrom->tag_value.s, pfrom->tag_value.len); presentity->from_tag.len= pfrom->tag_value.len; size+= pfrom->tag_value.len; if(record_route.len && record_route.s) { presentity->record_route.s= (char*)presentity + size; memcpy(presentity->record_route.s, record_route.s, record_route.len); presentity->record_route.len= record_route.len; size+= record_route.len; pkg_free(record_route.s); record_route.s = NULL; } presentity->contact.s= (char*)presentity + size; memcpy(presentity->contact.s, hentity->contact.s, hentity->contact.len); presentity->contact.len= hentity->contact.len; size+= hentity->contact.len; if(hentity->id.s) { presentity->id.s=(char*)presentity+ size; memcpy(presentity->id.s, hentity->id.s, hentity->id.len); presentity->id.len= hentity->id.len; size+= presentity->id.len; } if(hentity->extra_headers) { presentity->extra_headers= (str*)((char*)presentity+ size); size+= sizeof(str); presentity->extra_headers->s=(char*)presentity+ size; memcpy(presentity->extra_headers->s, hentity->extra_headers->s, hentity->extra_headers->len); presentity->extra_headers->len= hentity->extra_headers->len; size+= hentity->extra_headers->len; } /* write the remote contact filed */ presentity->remote_contact.s= (char*)shm_malloc(contact.len* sizeof(char)); if(presentity->remote_contact.s==NULL) { ERR_MEM(SHARE_MEM); } memcpy(presentity->remote_contact.s, contact.s, contact.len); presentity->remote_contact.len= contact.len; presentity->event|= hentity->event; presentity->flag= hentity->flag; presentity->etag.s= NULL; presentity->cseq= cseq; presentity->desired_expires= hentity->desired_expires; presentity->expires= lexpire+ (int)time(NULL); if(BLA_SUBSCRIBE & presentity->flag) { LM_DBG("BLA_SUBSCRIBE FLAG inserted\n"); } LM_DBG("record for subscribe from %.*s to %.*s inserted in datatbase\n", presentity->watcher_uri->len, presentity->watcher_uri->s, presentity->pres_uri->len, presentity->pres_uri->s); if (dbmode==PUA_DB_ONLY) { if (pua_dbf.end_transaction) { if (pua_dbf.end_transaction(pua_db) < 0) { LM_ERR("in end_transaction\n"); goto error; } } if (pua_dbf.start_transaction) { if (pua_dbf.start_transaction(pua_db, db_table_lock) < 0) { LM_ERR("in start_transaction\n"); goto error; } } if (convert_temporary_dialog_puadb(presentity) < 0) { LM_ERR("Could not convert temporary dialog into a dialog\n"); goto error; } } else { if (convert_temporary_dialog(presentity) < 0) { LM_ERR("Could not convert temporary dialog into a dialog\n"); goto error; } } done: if(hentity->ua_flag == REQ_OTHER) { hentity->flag= flag; run_pua_callbacks( hentity, msg); } if (dbmode == PUA_DB_ONLY && pua_dbf.end_transaction && end_transaction) { if (pua_dbf.end_transaction(pua_db) < 0) { LM_ERR("in end_transaction\n"); goto error; } } goto end; error: if (presentity) { if (presentity->remote_contact.s) shm_free(presentity->remote_contact.s); shm_free(presentity); } if(record_route.s) pkg_free(record_route.s); if (dbmode == PUA_DB_ONLY && pua_dbf.abort_transaction) { if (pua_dbf.abort_transaction(pua_db) < 0) LM_ERR("in abort_transaction\n"); } end: if(hentity) { shm_free(hentity); hentity= NULL; } free_to_params(&TO); return; }
static inline char* parse_to_param(char *buffer, char *end, struct to_body *to_b, int *returned_status) { struct to_param *param; int status; int saved_status; char *tmp; param=0; status=E_PARA_VALUE; saved_status=E_PARA_VALUE; for( tmp=buffer; tmp<end; tmp++) { switch(*tmp) { case ' ': case '\t': switch (status) { case TAG3: param->type=TAG_PARAM; case PARA_NAME: case TAG1: case TAG2: param->name.len = tmp-param->name.s; status = S_EQUAL; break; case PARA_VALUE_TOKEN: param->value.len = tmp-param->value.s; status = E_PARA_VALUE; add_param( param , to_b ); break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now =' '*/ status=saved_status; break; } break; case '\n': switch (status) { case S_PARA_NAME: case S_EQUAL: case S_PARA_VALUE: case E_PARA_VALUE: saved_status=status; status=F_LF; break; case TAG3: param->type=TAG_PARAM; case PARA_NAME: case TAG1: case TAG2: param->name.len = tmp-param->name.s; saved_status = S_EQUAL; status = F_LF; break; case PARA_VALUE_TOKEN: param->value.len = tmp-param->value.s; saved_status = E_PARA_VALUE; status = F_LF; add_param( param , to_b ); break; case F_CR: status=F_CRLF; break; case F_CRLF: case F_LF: status=saved_status; goto endofheader; default: goto parse_error; } break; case '\r': switch (status) { case S_PARA_NAME: case S_EQUAL: case S_PARA_VALUE: case E_PARA_VALUE: saved_status=status; status=F_CR; break; case TAG3: param->type=TAG_PARAM; case PARA_NAME: case TAG1: case TAG2: param->name.len = tmp-param->name.s; saved_status = S_EQUAL; status = F_CR; break; case PARA_VALUE_TOKEN: param->value.len = tmp-param->value.s; saved_status = E_PARA_VALUE; status = F_CR; add_param( param , to_b ); break; case F_CRLF: case F_CR: case F_LF: status=saved_status; goto endofheader; default: goto parse_error; } break; case 0: switch (status) { case PARA_NAME: param->name.len = tmp-param->name.s; case S_EQUAL: case S_PARA_VALUE: if (param->type==TAG_PARAM) goto parse_error; param->value.s = tmp; case PARA_VALUE_TOKEN: status = E_PARA_VALUE; param->value.len = tmp-param->value.s; add_param( param , to_b ); case E_PARA_VALUE: saved_status = status; goto endofheader; break; default: goto parse_error; } break; case '\\': switch (status) { case PARA_VALUE_QUOTED: switch (*(tmp+1)) { case '\r': case '\n': break; default: tmp++; } default: goto parse_error; } break; case '"': switch (status) { case S_PARA_VALUE: param->value.s = tmp+1; status = PARA_VALUE_QUOTED; break; case PARA_VALUE_QUOTED: param->value.len=tmp-param->value.s ; add_param( param , to_b ); status = E_PARA_VALUE; break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: goto parse_error; } break; case ';' : switch (status) { case PARA_VALUE_QUOTED: break; case PARA_NAME: param->name.len = tmp-param->name.s; case S_EQUAL: case S_PARA_VALUE: if (param->type==TAG_PARAM) goto parse_error; param->value.s = tmp; case PARA_VALUE_TOKEN: param->value.len=tmp-param->value.s; add_param(param,to_b); case E_PARA_VALUE: param = (struct to_param*) pkg_malloc(sizeof(struct to_param)); if (!param){ LM_ERR("out of pkg memory\n" ); goto error; } memset(param,0,sizeof(struct to_param)); param->type=GENERAL_PARAM; status = S_PARA_NAME; break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: goto parse_error; } break; case 'T': case 't' : switch (status) { case PARA_VALUE_QUOTED: case PARA_VALUE_TOKEN: case PARA_NAME: break; case S_PARA_NAME: param->name.s = tmp; status = TAG1; break; case S_PARA_VALUE: param->value.s = tmp; status = PARA_VALUE_TOKEN; break; case TAG1: case TAG2: case TAG3: status = PARA_NAME; break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: goto parse_error; } break; case 'A': case 'a' : switch (status) { case PARA_VALUE_QUOTED: case PARA_VALUE_TOKEN: case PARA_NAME: break; case S_PARA_NAME: param->name.s = tmp; status = PARA_NAME; break; case S_PARA_VALUE: param->value.s = tmp; status = PARA_VALUE_TOKEN; break; case TAG1: status = TAG2; break; case TAG2: case TAG3: status = PARA_NAME; break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: goto parse_error; } break; case 'G': case 'g' : switch (status) { case PARA_VALUE_QUOTED: case PARA_VALUE_TOKEN: case PARA_NAME: break; case S_PARA_NAME: param->name.s = tmp; status = PARA_NAME; break; case S_PARA_VALUE: param->value.s = tmp; status = PARA_VALUE_TOKEN; break; case TAG1: case TAG3: status = PARA_NAME; break; case TAG2: status = TAG3; break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: goto parse_error; } break; case '=': switch (status) { case PARA_VALUE_QUOTED: break; case TAG3: param->type=TAG_PARAM; case PARA_NAME: case TAG1: case TAG2: param->name.len = tmp-param->name.s; status = S_PARA_VALUE; break; case S_EQUAL: status = S_PARA_VALUE; break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: goto parse_error; } break; default: switch (status) { case TAG1: case TAG2: case TAG3: status = PARA_NAME; break; case PARA_VALUE_TOKEN: case PARA_NAME: case PARA_VALUE_QUOTED: break; case S_PARA_NAME: param->name.s = tmp; status = PARA_NAME; break; case S_PARA_VALUE: param->value.s = tmp; status = PARA_VALUE_TOKEN; break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: LM_ERR("spitting out [%c] in status %d\n",*tmp,status ); goto error; } }/*switch*/ }/*for*/ endofheader: if (param && (saved_status==S_EQUAL||saved_status==S_PARA_VALUE) ) { saved_status = E_PARA_VALUE; param->value.s= 0; param->value.len=0; if (param->type==TAG_PARAM) goto parse_error; add_param(param, to_b); } *returned_status=saved_status; return tmp; parse_error: LM_ERR("unexpected char [%c] in status %d: <<%.*s>> .\n", *tmp,status, (int)(tmp-buffer), ZSW(buffer)); error: if (param) pkg_free(param); free_to_params(to_b); to_b->error=PARSE_ERROR; *returned_status = status; return tmp; }
void free_to(struct to_body* tb) { free_to_params(tb); pkg_free(tb); }
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 dialoginfo_set(struct sip_msg* msg, char* flag_pv, char* str2) { struct dlg_cell * dlg; str peer_uri= {0, 0}; /* constructed from TO display name and RURI */ struct to_body* from, peer_to_body, FROM, *to; str* ruri; int len =0,ret=-1; char flag= DLG_PUB_AB; static char buf[256]; int buf_len= 255; str flag_str; char caller_buf[256], callee_buf[256]; pv_value_t tok; peer_to_body.param_lst = FROM.param_lst = NULL; if (msg->REQ_METHOD != METHOD_INVITE) return 1; if(dlg_api.create_dlg(msg,0)< 0) { LM_ERR("Failed to create dialog\n"); return -1; } dlg = dlg_api.get_dlg(); LM_DBG("new INVITE dialog created: from=%.*s\n", dlg->from_uri.len, dlg->from_uri.s); from = get_from(msg); /* if defined overwrite */ if(caller_spec_param.s) /* if parameter defined */ { memset(&tok, 0, sizeof(pv_value_t)); if(pv_get_spec_value(msg, &caller_spec, &tok) < 0) /* if value set */ { LM_ERR("Failed to get caller value\n"); return -1; } if(tok.flags&PV_VAL_STR) { str caller_str; if(tok.rs.len + CRLF_LEN > buf_len) { LM_ERR("Buffer overflow"); return -1; } trim(&tok.rs); memcpy(caller_buf, tok.rs.s, tok.rs.len); len = tok.rs.len; if(strncmp(tok.rs.s+len-CRLF_LEN, CRLF, CRLF_LEN)) { memcpy(caller_buf + len, CRLF, CRLF_LEN); len+= CRLF_LEN; } parse_to(caller_buf, caller_buf+len , &FROM); if(FROM.error != PARSE_OK) { LM_ERR("Failed to parse caller specification - not a valid uri\n"); goto end; } from = &FROM; caller_str.s = caller_buf; caller_str.len = len; LM_DBG("caller: %*s- len= %d\n", len, caller_buf, len); /* store caller in a dlg variable */ if(dlg_api.store_dlg_value(dlg, &entity_dlg_var, &caller_str)< 0) { LM_ERR("Failed to store dialog ruri\n"); goto end; } } } peer_uri.s = callee_buf; if(callee_spec_param.s) { memset(&tok, 0, sizeof(pv_value_t)); if(pv_get_spec_value(msg, &callee_spec, &tok) < 0) { LM_ERR("Failed to get callee value\n"); goto end; } if(tok.flags&PV_VAL_STR) { if(tok.rs.len + CRLF_LEN > buf_len) { LM_ERR("Buffer overflow"); goto end; } trim(&tok.rs); memcpy(peer_uri.s, tok.rs.s, tok.rs.len); len = tok.rs.len; if(strncmp(tok.rs.s+len-CRLF_LEN, CRLF, CRLF_LEN)) { memcpy(peer_uri.s + len, CRLF, CRLF_LEN); len+= CRLF_LEN; } peer_uri.len = len; } else goto default_callee; } else { default_callee: ruri = GET_RURI(msg); to = get_to(msg); len= to->display.len + 2 + ruri->len + CRLF_LEN; if(len > buf_len) { LM_ERR("Buffer overflow\n"); goto end; } len = 0; if(to->display.len && to->display.s) { memcpy(peer_uri.s, to->display.s, to->display.len); peer_uri.s[to->display.len]='<'; len = to->display.len + 1; } memcpy(peer_uri.s + len, ruri->s, ruri->len); len+= ruri->len; if(to->display.len) { peer_uri.s[len++]='>'; } memcpy(peer_uri.s + len, CRLF, CRLF_LEN); len+= CRLF_LEN; peer_uri.len = len; } LM_DBG("Peer uri = %.*s\n", peer_uri.len, peer_uri.s); parse_to(peer_uri.s, peer_uri.s+peer_uri.len, &peer_to_body); if(peer_to_body.error != PARSE_OK) { LM_ERR("Failed to peer uri [%.*s]\n", peer_uri.len, peer_uri.s); goto end; } /* store peer uri in dialog structure */ if(dlg_api.store_dlg_value(dlg, &peer_dlg_var, &peer_uri)< 0) { LM_ERR("Failed to store dialog ruri\n"); goto end; } /* store flag, if defined */ if(flag_pv) { if(pv_printf(msg, (pv_elem_t*)flag_pv, buf, &buf_len)<0) { LM_ERR("cannot print the format\n"); goto end; } if(!check_flag(buf, buf_len)) { LM_ERR("Wrong value for flag\n"); goto end; } flag = buf[0]; flag_str.s = buf; flag_str.len = buf_len; if(dlg_api.store_dlg_value(dlg, &flag_dlg_var, &flag_str)< 0) { LM_ERR("Failed to store dialog ruri\n"); goto end; } } /* register dialog callbacks which triggers sending PUBLISH */ if (dlg_api.register_dlgcb(dlg, DLGCB_FAILED| DLGCB_CONFIRMED | DLGCB_TERMINATED | DLGCB_EXPIRED | DLGCB_RESPONSE_WITHIN | DLGCB_EARLY, __dialog_sendpublish, 0, 0) != 0) { LM_ERR("cannot register callback for interesting dialog types\n"); goto end; } #ifdef PUA_DIALOGINFO_DEBUG /* dialog callback testing (registered last to be executed first) */ if (dlg_api.register_dlgcb(dlg, DLGCB_FAILED| DLGCB_CONFIRMED | DLGCB_REQ_WITHIN | DLGCB_TERMINATED | DLGCB_EXPIRED | DLGCB_EARLY | DLGCB_RESPONSE_FWDED | DLGCB_RESPONSE_WITHIN | DLGCB_MI_CONTEXT | DLGCB_DESTROY, __dialog_cbtest, NULL, NULL) != 0) { LM_ERR("cannot register callback for all dialog types\n"); goto end; } #endif if(publish_on_trying) { if(flag == DLG_PUB_A || flag == DLG_PUB_AB) dialog_publish("trying", from, &peer_to_body, &(dlg->callid), 1, DEFAULT_CREATED_LIFETIME, 0, 0); if(flag == DLG_PUB_B || flag == DLG_PUB_AB) dialog_publish("trying", &peer_to_body, from, &(dlg->callid), 0, DEFAULT_CREATED_LIFETIME, 0, 0); } ret=1; end: if (peer_to_body.param_lst) free_to_params(&peer_to_body); if (FROM.param_lst) free_to_params(&FROM); return ret; }
static void __dialog_sendpublish(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params) { str tag = {0,0}; struct to_body from; str peer_uri= {0, 0}; char flag = DLG_PUB_AB; str flag_str; struct to_body peer_to_body; str entity_uri= {0, 0}; int buf_len = 255; struct sip_msg* msg = _params->msg; flag_str.s = &flag; flag_str.len = 1; memset(&from, 0, sizeof(struct to_body)); memset(&peer_to_body, 0, sizeof(struct to_body)); from.uri = dlg->from_uri; peer_uri.len = buf_len; peer_uri.s = (char*)pkg_malloc(buf_len); if(peer_uri.s == NULL) { LM_ERR("No more memory\n"); goto error; } /* extract the peer_uri */ if(dlg_api.fetch_dlg_value(dlg, &peer_dlg_var, &peer_uri, 1) < 0 || peer_uri.len==0) { LM_ERR("Failed to fetch peer uri dialog variable\n"); goto error; } LM_DBG("peer_uri = %.*s\n", peer_uri.len, peer_uri.s); parse_to(peer_uri.s, peer_uri.s+peer_uri.len, &peer_to_body); if(peer_to_body.error != PARSE_OK) { LM_ERR("Failed to peer uri [%.*s]\n", peer_uri.len, peer_uri.s); goto error; } /* try to extract the flag */ dlg_api.fetch_dlg_value(dlg, &flag_dlg_var, &flag_str, 1); LM_DBG("flag = %c\n", flag); entity_uri.len = buf_len; entity_uri.s = (char*)pkg_malloc(buf_len); if(entity_uri.s == NULL) { LM_ERR("No more memory\n"); goto error; } /* check if entity is also custom */ if(dlg_api.fetch_dlg_value(dlg, &entity_dlg_var, &entity_uri, 1) == 0) { /* overwrite from with this value */ parse_to(entity_uri.s, entity_uri.s + entity_uri.len, &from); if(from.error != PARSE_OK) { LM_ERR("Wrong format for entity body\n"); goto error; } LM_DBG("entity_uri = %.*s\n", entity_uri.len, entity_uri.s); LM_DBG("from uri = %.*s\n", from.uri.len, from.uri.s); } switch (type) { case DLGCB_FAILED: case DLGCB_TERMINATED: case DLGCB_EXPIRED: LM_DBG("dialog over, from=%.*s\n", dlg->from_uri.len, dlg->from_uri.s); if(flag == DLG_PUB_AB || flag == DLG_PUB_A) dialog_publish("terminated", &from, &peer_to_body, &(dlg->callid), 1, 0, 0, 0); if(flag == DLG_PUB_AB || flag == DLG_PUB_B) dialog_publish("terminated", &peer_to_body, &from, &(dlg->callid), 0, 0, 0, 0); break; case DLGCB_RESPONSE_WITHIN: if (get_cseq(msg)->method_id==METHOD_INVITE) { if (msg->flags & nopublish_flag) { LM_DBG("nopublish flag was set for this INVITE\n"); break; } LM_DBG("nopublish flag not set for this INVITE, will publish\n"); } else { /* no publish for non-INVITEs */ break; } case DLGCB_CONFIRMED: LM_DBG("dialog confirmed, from=%.*s\n", dlg->from_uri.len, dlg->from_uri.s); if(flag == DLG_PUB_AB || flag == DLG_PUB_A) dialog_publish("confirmed", &from, &peer_to_body, &(dlg->callid), 1, dlg->lifetime, 0, 0); if(flag == DLG_PUB_AB || flag == DLG_PUB_B) dialog_publish("confirmed", &peer_to_body, &from, &(dlg->callid), 0, dlg->lifetime, 0, 0); break; case DLGCB_EARLY: LM_DBG("dialog is early, from=%.*s\n", from.uri.len, from.uri.s); if (include_tags) { /* get to tag*/ if ( !_params->msg->to && ((parse_headers(_params->msg, HDR_TO_F,0)<0) || !_params->msg->to) ) { LM_ERR("bad reply or missing TO hdr :-/\n"); tag.s = 0; tag.len = 0; } else { tag = get_to(_params->msg)->tag_value; if (tag.s==0 || tag.len==0) { LM_ERR("missing TAG param in TO hdr :-/\n"); tag.s = 0; tag.len = 0; } } if(flag == DLG_PUB_AB || flag == DLG_PUB_A) { if (caller_confirmed) { dialog_publish("confirmed", &from, &peer_to_body, &(dlg->callid), 1, dlg->lifetime, &(dlg->legs[DLG_CALLER_LEG].tag), &tag); } else { dialog_publish("early", &from, &peer_to_body, &(dlg->callid), 1, dlg->lifetime, &(dlg->legs[DLG_CALLER_LEG].tag), &tag); } } if(flag == DLG_PUB_AB || flag == DLG_PUB_B) { dialog_publish("early", &peer_to_body, &from, &(dlg->callid), 0, dlg->lifetime, &tag, &(dlg->legs[DLG_CALLER_LEG].tag)); } } else { if(flag == DLG_PUB_AB || flag == DLG_PUB_A) { if (caller_confirmed) { dialog_publish("confirmed", &from, &peer_to_body, &(dlg->callid), 1, dlg->lifetime, 0, 0); } else { dialog_publish("early", &from, &peer_to_body, &(dlg->callid), 1, dlg->lifetime, 0, 0); } } if(flag == DLG_PUB_AB || flag == DLG_PUB_B) { dialog_publish("early", &peer_to_body, &from, &(dlg->callid), 0, dlg->lifetime, 0, 0); } } break; default: LM_ERR("unhandled dialog callback type %d received, from=%.*s\n", type, dlg->from_uri.len, dlg->from_uri.s); if(flag == DLG_PUB_AB || flag == DLG_PUB_A) dialog_publish("terminated", &from, &peer_to_body, &(dlg->callid), 1, 0, 0, 0); if(flag == DLG_PUB_AB || flag == DLG_PUB_B) dialog_publish("terminated", &peer_to_body, &from, &(dlg->callid), 0, 0, 0, 0); } error: if(peer_uri.s) pkg_free(peer_uri.s); if(entity_uri.s) pkg_free(entity_uri.s); if (peer_to_body.param_lst) free_to_params(&peer_to_body); if (from.param_lst) free_to_params(&from); }
char *parse_addr_spec(char *const buffer, const char *const end, struct to_body *const to_b, const int allow_comma_sep) { int status; int saved_status; char *tmp, *foo; saved_status = START_TO; /* fixes gcc 4.x warning */ status = START_TO; memset(to_b, 0, sizeof(struct to_body)); to_b->error = PARSE_OK; foo = 0; for(tmp = buffer; tmp < end; tmp++) { switch(*tmp) { case ' ': case '\t': switch(status) { case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now =' '*/ status = saved_status; break; case URI_ENCLOSED: to_b->uri.len = tmp - to_b->uri.s; status = E_URI_ENCLOSED; break; case URI_OR_TOKEN: foo = tmp; status = MAYBE_URI_END; break; case DISPLAY_TOKEN: foo = tmp; status = DISPLAY_TOKEN_SP; break; } break; case '\n': switch(status) { case URI_OR_TOKEN: foo = tmp; status = MAYBE_URI_END; case MAYBE_URI_END: case DISPLAY_TOKEN_SP: case E_DISPLAY_QUOTED: case END: saved_status = status; status = F_LF; break; case DISPLAY_TOKEN: foo = tmp; saved_status = DISPLAY_TOKEN_SP; status = F_LF; break; case F_CR: status = F_CRLF; break; case F_CRLF: case F_LF: status = saved_status; goto endofheader; default: LM_ERR("unexpected char [%c] in status %d: [%.*s] .\n", *tmp, status, (int)(tmp - buffer), ZSW(buffer)); goto error; } break; case '\r': switch(status) { case URI_OR_TOKEN: foo = tmp; status = MAYBE_URI_END; case MAYBE_URI_END: case DISPLAY_TOKEN_SP: case E_DISPLAY_QUOTED: case END: saved_status = status; status = F_CR; break; case DISPLAY_TOKEN: foo = tmp; saved_status = DISPLAY_TOKEN_SP; status = F_CR; break; case F_CRLF: case F_CR: case F_LF: status = saved_status; goto endofheader; default: LM_ERR("unexpected char [%c] in status %d: [%.*s] .\n", *tmp, status, (int)(tmp - buffer), ZSW(buffer)); goto error; } break; case 0: switch(status) { case URI_OR_TOKEN: case MAYBE_URI_END: to_b->uri.len = tmp - to_b->uri.s; case END: saved_status = status = END; goto endofheader; default: LM_ERR("unexpected char [%c] in status %d: [%.*s] .\n", *tmp, status, (int)(tmp - buffer), ZSW(buffer)); goto error; } break; case '\\': switch(status) { case DISPLAY_QUOTED: tmp++; /* jump over next char */ break; default: LM_ERR("unexpected char [%c] in status %d: [%.*s] .\n", *tmp, status, (int)(tmp - buffer), ZSW(buffer)); goto error; } break; case '<': switch(status) { case START_TO: to_b->body.s = tmp; status = S_URI_ENCLOSED; break; case DISPLAY_QUOTED: break; case E_DISPLAY_QUOTED: status = S_URI_ENCLOSED; break; case URI_OR_TOKEN: case DISPLAY_TOKEN: to_b->display.len = tmp - to_b->display.s; status = S_URI_ENCLOSED; break; case DISPLAY_TOKEN_SP: case MAYBE_URI_END: to_b->display.len = foo - to_b->display.s; status = S_URI_ENCLOSED; break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: LM_ERR("unexpected char [%c] in status %d: [%.*s] .\n", *tmp, status, (int)(tmp - buffer), ZSW(buffer)); goto error; } break; case '>': switch(status) { case DISPLAY_QUOTED: break; case URI_ENCLOSED: to_b->uri.len = tmp - to_b->uri.s; case E_URI_ENCLOSED: status = END; foo = 0; break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: LM_ERR("unexpected char [%c] in status %d: [%.*s] .\n", *tmp, status, (int)(tmp - buffer), ZSW(buffer)); goto error; } break; case '"': switch(status) { case START_TO: to_b->body.s = tmp; to_b->display.s = tmp; status = DISPLAY_QUOTED; break; case DISPLAY_QUOTED: status = E_DISPLAY_QUOTED; to_b->display.len = tmp - to_b->display.s + 1; break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: LM_ERR("unexpected char [%c] in status %d: [%.*s] .\n", *tmp, status, (int)(tmp - buffer), buffer); goto error; } break; case ';': switch(status) { case DISPLAY_QUOTED: case URI_ENCLOSED: break; case URI_OR_TOKEN: foo = tmp; case MAYBE_URI_END: to_b->uri.len = foo - to_b->uri.s; case END: to_b->body.len = tmp - to_b->body.s; tmp = parse_to_param( tmp, end, to_b, allow_comma_sep, &saved_status); goto endofheader; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: LM_ERR("unexpected char [%c] in status %d: [%.*s] .\n", *tmp, status, (int)(tmp - buffer), buffer); goto error; } break; case ',': if(allow_comma_sep) { switch(status) { case DISPLAY_QUOTED: case URI_ENCLOSED: break; case URI_OR_TOKEN: foo = tmp; case MAYBE_URI_END: to_b->uri.len = foo - to_b->uri.s; case END: to_b->body.len = tmp - to_b->body.s; saved_status = END; goto endofheader; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: LM_ERR("unexpected char [%c] in status %d: [%.*s] " ".\n", *tmp, status, (int)(tmp - buffer), buffer); goto error; } break; } /* If commas not allowed treat as a default character */ default: switch(status) { case START_TO: to_b->uri.s = to_b->body.s = tmp; status = URI_OR_TOKEN; to_b->display.s = tmp; break; case S_URI_ENCLOSED: to_b->uri.s = tmp; status = URI_ENCLOSED; break; case MAYBE_URI_END: case DISPLAY_TOKEN_SP: status = DISPLAY_TOKEN; case DISPLAY_QUOTED: case DISPLAY_TOKEN: case URI_ENCLOSED: case URI_OR_TOKEN: break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: LM_DBG("spitting out [%c] in status %d\n", *tmp, status); goto error; } } /*char switch*/ } /*for*/ /* Reached end of buffer */ switch(status) { case URI_OR_TOKEN: case MAYBE_URI_END: case END: saved_status = status; foo = tmp; } endofheader: if(to_b->display.len == 0) to_b->display.s = 0; status = saved_status; LM_DBG("end of header reached, state=%d\n", status); /* check if error*/ switch(status) { case URI_OR_TOKEN: case MAYBE_URI_END: to_b->uri.len = foo - to_b->uri.s; case END: to_b->body.len = tmp - to_b->body.s; case E_PARA_VALUE: break; default: LM_ERR("invalid To - unexpected " "end of header in state %d\n", status); goto error; } return tmp; error: free_to_params(to_b); to_b->error = PARSE_ERROR; return tmp; }
int ki_pua_update_contact(struct sip_msg* msg) { ua_pres_t* p, hentity; str contact; struct to_body *pto = NULL, TO = {0}, *pfrom = NULL; unsigned int hash_code; if ( parse_headers(msg,HDR_EOH_F, 0)==-1 ) { LM_ERR("when parsing headers\n"); return -1; } /* find the record */ if( msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot parse callid header\n"); return -1; } if (!msg->from || !msg->from->body.s) { LM_ERR("cannot find 'from' header!\n"); return -1; } if (msg->from->parsed == NULL) { if ( parse_from_header( msg )<0 ) { LM_ERR("cannot parse From header\n"); return -1; } } pfrom = (struct to_body*)msg->from->parsed; if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0) { LM_ERR("no from tag value present\n"); return -1; } if( msg->to==NULL || msg->to->body.s==NULL) { LM_ERR("cannot parse TO header\n"); return -1; } 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_DBG("'To' header NOT parsed\n"); goto error; } pto = &TO; } if( pto->tag_value.s ==NULL || pto->tag_value.len == 0) { LM_ERR("no from tag value present\n"); goto error; } hentity.watcher_uri= &pto->uri; hentity.pres_uri= &pfrom->uri; hentity.call_id= msg->callid->body; hentity.to_tag= pto->tag_value; hentity.from_tag= pfrom->tag_value; /* extract the contact */ if(msg->contact== NULL || msg->contact->body.s== NULL) { LM_ERR("no contact header found in 200 OK reply"); goto error; } contact= msg->contact->body; if (dbmode==PUA_DB_ONLY) { update_contact_puadb(&hentity, &contact ); free_to_params(&TO); return(1); } hash_code= core_hash(hentity.pres_uri,hentity.watcher_uri, HASH_SIZE); lock_get(&HashT->p_records[hash_code].lock); p= get_dialog(&hentity, hash_code); if(p== NULL) { lock_release(&HashT->p_records[hash_code].lock); LM_ERR("no record for the dialog found in hash table\n"); goto error; } shm_free(p->remote_contact.s); if(!(p->remote_contact.len== contact.len && strncmp(p->remote_contact.s, contact.s, contact.len)==0)) { /* update remote contact */ shm_free(p->remote_contact.s); p->remote_contact.s= (char*)shm_malloc(contact.len* sizeof(char)); if(p->remote_contact.s== NULL) { LM_ERR("no more shared memory\n"); lock_release(&HashT->p_records[hash_code].lock); goto error; } memcpy(p->remote_contact.s, contact.s, contact.len); p->remote_contact.len= contact.len; } lock_release(&HashT->p_records[hash_code].lock); free_to_params(&TO); return 1; error: free_to_params(&TO); return -1; }
int bla_handle_notify(struct sip_msg* msg, char* s1, char* s2) { publ_info_t publ; struct to_body *pto = NULL, TO = {0}, *pfrom = NULL; str body; ua_pres_t dialog; unsigned int expires= 0; struct hdr_field* hdr; str subs_state; int found= 0; str extra_headers= {0, 0}; static char buf[255]; str contact; memset(&publ, 0, sizeof(publ_info_t)); memset(&dialog, 0, sizeof(ua_pres_t)); LM_DBG("start\n"); if ( parse_headers(msg,HDR_EOH_F, 0)==-1 ) { LM_ERR("parsing headers\n"); return -1; } if( msg->to==NULL || msg->to->body.s==NULL) { LM_ERR("cannot parse TO header\n"); goto error; } /* examine the to header */ 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_DBG("'To' header NOT parsed\n"); goto error; } pto = &TO; } publ.pres_uri= &pto->uri; dialog.watcher_uri= publ.pres_uri; if (pto->tag_value.s==NULL || pto->tag_value.len==0 ) { LM_ERR("NULL to_tag value\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_DBG(" ERROR 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.event= BLA_EVENT; dialog.flag= BLA_SUBSCRIBE; if(pua_is_dialog(&dialog)< 0) { LM_ERR("Notify in a non existing dialog\n"); goto error; } LM_DBG("found a matching dialog\n"); /* parse Subscription-State and extract expires if existing */ 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("No Subscription-State header found\n"); goto error; } subs_state= hdr->body; if(strncmp(subs_state.s, "terminated", 10)== 0) expires= 0; else if(strncmp(subs_state.s, "active", 6)== 0 || strncmp(subs_state.s, "pending", 7)==0 ) { char* sep= NULL; str exp= {0, 0}; sep= strchr(subs_state.s, ';'); if(sep== NULL) { LM_ERR("No expires found in Notify\n"); goto error; } if(strncmp(sep+1, "expires=", 8)!= 0) { LM_ERR("No expires found in Notify\n"); goto error; } exp.s= sep+ 9; sep= exp.s; while((*sep)>='0' && (*sep)<='9') { sep++; exp.len++; } if( str2int(&exp, &expires)< 0) { LM_ERR("while parsing int\n"); goto error; } } if ( get_content_length(msg) == 0 ) { LM_ERR("content length= 0\n"); goto error; } else { 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 ); } if(msg->contact== NULL || msg->contact->body.s== NULL) { LM_ERR("no contact header found"); goto error; } if( parse_contact(msg->contact) <0 ) { LM_ERR(" cannot parse contact header\n"); goto error; } if(msg->contact->parsed == NULL) { LM_ERR("cannot parse contact header\n"); goto error; } contact = ((contact_body_t* )msg->contact->parsed)->contacts->uri; /* build extra_headers with Sender*/ extra_headers.s= buf; memcpy(extra_headers.s, header_name.s, header_name.len); extra_headers.len= header_name.len; memcpy(extra_headers.s+extra_headers.len,": ",2); extra_headers.len+= 2; memcpy(extra_headers.s+ extra_headers.len, contact.s, contact.len); extra_headers.len+= contact.len; memcpy(extra_headers.s+ extra_headers.len, CRLF, CRLF_LEN); extra_headers.len+= CRLF_LEN; publ.body= &body; publ.source_flag= BLA_PUBLISH; publ.expires= expires; publ.event= BLA_EVENT; publ.extra_headers= &extra_headers; if(pua_send_publish(&publ)< 0) { LM_ERR("while sending Publish\n"); goto error; } xmlCleanupParser(); xmlMemoryDump(); free_to_params(&TO); return 1; error: free_to_params(&TO); return 0; }
char* parse_to(char* buffer, char *end, struct to_body *to_b) { int status; int saved_status; char *tmp; char *end_mark; status=START_TO; saved_status=START_TO; memset(to_b, 0, sizeof(struct to_body)); to_b->error=PARSE_OK; end_mark=0; for( tmp=buffer; tmp<end; tmp++) { switch(*tmp) { case ' ': case '\t': switch (status) { case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now =' '*/ status=saved_status; break; case URI_ENCLOSED: to_b->uri.len = tmp - to_b->uri.s; status = E_URI_ENCLOSED; break; case URI_OR_TOKEN: status = MAYBE_URI_END; end_mark = tmp; break; case DISPLAY_TOKEN: end_mark = tmp; status = DISPLAY_TOKEN2; break; } break; case '\n': switch (status) { case URI_OR_TOKEN: end_mark = tmp; status = MAYBE_URI_END; case MAYBE_URI_END: case DISPLAY_TOKEN: case DISPLAY_TOKEN2: case E_DISPLAY_QUOTED: case END: saved_status=status; status=F_LF; break; case F_CR: status=F_CRLF; break; case F_CRLF: case F_LF: status=saved_status; goto endofheader; default: goto parse_error; } break; case '\r': switch (status) { case URI_OR_TOKEN: end_mark = tmp; status = MAYBE_URI_END; case MAYBE_URI_END: case DISPLAY_TOKEN: case DISPLAY_TOKEN2: case E_DISPLAY_QUOTED: case END: saved_status=status; status=F_CR; break; case F_CRLF: case F_CR: case F_LF: status=saved_status; goto endofheader; default: goto parse_error; } break; case 0: switch (status) { case URI_OR_TOKEN: case MAYBE_URI_END: to_b->uri.len = tmp - to_b->uri.s; case END: saved_status = status = END; goto endofheader; default: goto parse_error; } break; case '\\': switch (status) { case DISPLAY_QUOTED: tmp++; /* jump over next char */ break; default: goto parse_error; } break; case '<': switch (status) { case START_TO: to_b->body.s=tmp; status = S_URI_ENCLOSED; break; case DISPLAY_QUOTED: break; case E_DISPLAY_QUOTED: status = S_URI_ENCLOSED; break; case URI_OR_TOKEN: case DISPLAY_TOKEN: end_mark = tmp; case DISPLAY_TOKEN2: case MAYBE_URI_END: to_b->display.len=end_mark-to_b->display.s; status = S_URI_ENCLOSED; break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: goto parse_error; } break; case '>': switch (status) { case DISPLAY_QUOTED: break; case URI_ENCLOSED: to_b->uri.len = tmp - to_b->uri.s; case E_URI_ENCLOSED: status = END; break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: goto parse_error; } break; case '"': switch (status) { case START_TO: to_b->body.s = tmp; to_b->display.s = tmp; status = DISPLAY_QUOTED; break; case DISPLAY_QUOTED: status = E_DISPLAY_QUOTED; to_b->display.len = tmp-to_b->display.s+1; break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: goto parse_error; } break; case ';' : switch (status) { case DISPLAY_QUOTED: case DISPLAY_TOKEN: case URI_ENCLOSED: break; case URI_OR_TOKEN: end_mark = tmp; case MAYBE_URI_END: to_b->uri.len = end_mark - to_b->uri.s; case END: to_b->body.len = tmp-to_b->body.s; tmp = parse_to_param(tmp,end,to_b,&saved_status); goto endofheader; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: goto parse_error; } break; default: switch (status) { case START_TO: to_b->uri.s = to_b->body.s = tmp; status = URI_OR_TOKEN; to_b->display.s=tmp; break; case S_URI_ENCLOSED: to_b->uri.s=tmp; status=URI_ENCLOSED; break; case MAYBE_URI_END: case DISPLAY_TOKEN2: status = DISPLAY_TOKEN; case DISPLAY_QUOTED: case DISPLAY_TOKEN: case URI_ENCLOSED: case URI_OR_TOKEN: break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: LM_DBG("spitting out [%c] in status %d\n", *tmp,status ); goto error; } }/*char switch*/ }/*for*/ endofheader: if (to_b->display.len==0) to_b->display.s=0; status=saved_status; LM_DBG("end of header reached, state=%d\n", status); /* check if error*/ switch(status){ case MAYBE_URI_END: to_b->uri.len = end_mark - to_b->uri.s; case END: to_b->body.len = tmp - to_b->body.s; case E_PARA_VALUE: break; default: LM_ERR("unexpected end of header in state %d\n", status); goto error; } LM_DBG("display={%.*s}, ruri={%.*s}\n", to_b->display.len, ZSW(to_b->display.s), to_b->uri.len, ZSW(to_b->uri.s)); return tmp; parse_error: LM_ERR("unexpected char [%c] in status %d: <<%.*s>> .\n", *tmp,status, (int)(tmp-buffer), buffer); error: to_b->error=PARSE_ERROR; free_to_params(to_b); return tmp; }
int Notify2Xmpp(struct sip_msg* msg, char* s1, char* s2) { struct to_body *pto, TO = {0}, *pfrom = NULL; str to_uri; char* uri= NULL; str from_uri; struct hdr_field* hdr= NULL; str body; int is_terminated= 0; str id; ua_pres_t dialog; int event_flag= 0; memset(&dialog, 0, sizeof(ua_pres_t)); LM_DBG("start...\n\n"); 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; } 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"); goto error; } pto = &TO; } dialog.watcher_uri= &pto->uri; uri=(char*)pkg_malloc(sizeof(char)*( pto->uri.len+1)); if(uri== NULL) { LM_ERR("no more memory\n"); goto error; } memcpy(uri, pto->uri.s, pto->uri.len); uri[pto->uri.len]= '\0'; to_uri.s= duri_sip_xmpp(uri); if(to_uri.s== NULL) { LM_ERR("while decoding sip uri in xmpp\n"); pkg_free(uri); goto error; } to_uri.len= strlen(to_uri.s); pkg_free(uri); if (pto->tag_value.s==NULL || pto->tag_value.len==0 ) { LM_ERR("to tag value not parsed\n"); goto error; } id= pto->tag_value; dialog.from_tag= id; 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("ERROR cannot find 'from' header!\n"); goto error; } if (msg->from->parsed == NULL) { LM_ERR("'From' header not parsed\n"); /* parsing from header */ if ( parse_from_header( msg )<0 ) { LM_ERR("ERROR cannot parse From header\n"); goto error; } } pfrom = (struct to_body*)msg->from->parsed; dialog.pres_uri= &pfrom->uri; uri=(char*)pkg_malloc(sizeof(char)*( pfrom->uri.len+1)); if(uri== NULL) { LM_ERR("no more memory\n"); goto error; } memcpy(uri, pfrom->uri.s, pfrom->uri.len); uri[pfrom->uri.len]= '\0'; from_uri.s= euri_sip_xmpp(uri); if(from_uri.s== NULL) { LM_ERR("while encoding sip uri in xmpp\n"); pkg_free(uri); goto error; } from_uri.len= strlen(from_uri.s); pkg_free(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|= XMPP_SUBSCRIBE; if(msg->event->body.len== 8 && (strncmp(msg->event->body.s,"presence",8 )==0)) event_flag|= PRESENCE_EVENT; else if(msg->event->body.len== 14 && (strncmp(msg->event->body.s,"presence.winfo",14 )==0)) event_flag|= PWINFO_EVENT; else { LM_ERR("wrong event\n"); goto error; } dialog.event= event_flag; if(pua_is_dialog(&dialog)< 0) // verify if within a stored dialog { LM_ERR("Notify in a non existing dialog\n"); goto error; } /*constructing the xml body*/ if(get_content_length(msg) == 0 ) { body.s= NULL; body.len= 0; } else { 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 ); } /* treat the two cases: event= presence & event=presence.winfo */ if(event_flag & PRESENCE_EVENT) { LM_DBG("PRESENCE\n"); hdr = msg->headers; while (hdr!= NULL) { if(cmp_hdrname_strzn(&hdr->name, "Subscription-State", 18)==0) break; hdr = hdr->next; } if(hdr && strncmp(hdr->body.s,"terminated", 10)== 0) { /* chack if reason timeout => don't send notification */ if(strncmp(hdr->body.s+11,"reason=timeout", 14)== 0) { LM_DBG("Received Notification with state" "terminated; reason= timeout=> don't send notification\n"); return 1; } is_terminated= 1; } if(build_xmpp_content(&to_uri, &from_uri, &body, &id, is_terminated)< 0) { LM_ERR("in function build_xmpp_content\n"); goto error; } } else { if(event_flag & PWINFO_EVENT) { LM_DBG("PRESENCE.WINFO\n"); hdr = msg->headers; while (hdr!= NULL) { if(cmp_hdrname_strzn(&hdr->name, "Subscription-State", 18)==0) break; hdr = hdr->next; } if(hdr && strncmp(hdr->body.s,"terminated", 10)== 0) { LM_DBG("Notify for presence.winfo with" " Subscription-State terminated- should not translate\n"); goto error; } if(winfo2xmpp(&to_uri, &body, &id)< 0) { LM_ERR("while sending subscription\n"); goto error; } } else { LM_ERR("Missing or unsupported event header field value\n"); goto error; } } free_to_params(&TO); return 1; error: free_to_params(&TO); return 0; }