static inline struct sip_msg *parse_ac_msg(hdr_flags_t flags,char *start,int len) { struct sip_msg *my_msg; my_msg=NULL; if(!(my_msg=pkg_malloc(sizeof(struct sip_msg)))){ LM_ERR("ac_reply: out of memory!\n"); goto error; } memset(my_msg,0,sizeof(struct sip_msg)); my_msg->buf=start; my_msg->len=len; LM_DBG("Action Message:[%.*s]\n",len,start); if(0>parse_msg(start,len,my_msg)){ LM_ERR("parse_ac_msg: parsing sip_msg"); goto error; } if(0>parse_headers(my_msg,flags,0)){ LM_ERR("parse_ac_msg: parsing headers\n"); goto error; } return my_msg; error: if(my_msg){ free_sip_msg_lite(my_msg); pkg_free(my_msg); } return NULL; }
/* Actions are composed as follows: * (the action length and type as always= 5 bytes) * * TODO performance speedup: instead of using * dynamically allocated memory for headers,body,totag,reason and my_msg * use static buffers. * */ int ac_sl_msg(as_p the_as,unsigned char processor_id,unsigned int flags,char *action,int len) { struct sip_msg *my_msg; str *uri; struct proxy_l *proxy; rr_t *my_route; int k,retval; //enum sip_protos proto; my_msg=NULL; k=0; proxy=0; if(!(my_msg = parse_ac_msg(HDR_EOH_F,action+k,len-k))){ LM_ERR("out of memory!\n"); goto error; } if(my_msg->first_line.type == SIP_REQUEST) LM_DBG("forwarding request:\"%.*s\" statelessly \n",my_msg->first_line.u.request.method.len+1+\ my_msg->first_line.u.request.uri.len,my_msg->first_line.u.request.method.s); else LM_DBG("forwarding reply:\"%.*s\" statelessly \n",my_msg->first_line.u.reply.status.len+1+\ my_msg->first_line.u.reply.reason.len,my_msg->first_line.u.reply.status.s); if (my_msg->route) { if (parse_rr(my_msg->route) < 0) { LM_ERR( "Error while parsing Route body\n"); goto error; } my_route = (rr_t*)my_msg->route->parsed; uri=&(my_route->nameaddr.uri); }else{ uri = GET_RURI(my_msg); } set_force_socket(my_msg, grep_sock_info(&my_msg->via1->host, my_msg->via1->port, my_msg->via1->proto) ); /* or also could be: my_msg->force_send_socket=the_as->binds[processor_id].bind_address; not sure which is better... */ /*proxy=uri2proxy(uri,PROTO_NONE); if (proxy==0) { LM_ERR("unable to create proxy from URI \n"); goto error; } proto=proxy->proto; */ //TODO my_msg->recvd if(0>forward_sl_request(my_msg,uri,PROTO_NONE)) goto error; retval=0; goto exit; error: retval = -1; exit: if(proxy){ free_proxy(proxy); pkg_free(proxy); } if(my_msg){ free_sip_msg_lite(my_msg); pkg_free(my_msg); } return retval; }
/** * ac_reply: UAS transaction Reply action. It replies to an incoming request with a response. * @param the_as The App Server that sent this action. * @param action action * @param len length * * function description * * Returns: what */ int ac_reply(as_p the_as,unsigned char processor_id,unsigned int flags,char *action,int len) { unsigned int hash_index,label,contentlength; struct cell *c=NULL; struct sip_msg *my_msg; struct to_body *tb; str new_header,body,totag; char *ttag; int i,k,retval; static char headers[MAX_HEADER]; struct as_uac_param *the_param; contentlength=0; ttag=NULL; my_msg=NULL; i=k=0; the_param=NULL; net2hostL(hash_index,action,k); net2hostL(label,action,k); if(seas_f.tmb.t_lookup_ident(&c,hash_index,label)<0){ LM_ERR("Failed to t_lookup_ident hash_idx=%d,label=%d\n",hash_index,label); goto error; } if(use_stats) action_stat(c); if(c->uas.status>=200){ LM_ERR("ac_reply: trying to reply to a \"%.*s\" transaction" "that is already in completed state\n",REQ_LINE(c->uas.request).method.len,REQ_LINE(c->uas.request).method.s); goto error; } if (!(my_msg=parse_ac_msg(HDR_EOH_F,action+k,len-k))) { LM_ERR("Failed to parse_ac_msg hash_idx=%d,label=%d\n",hash_index,label); goto error; } tb=(struct to_body*)my_msg->to->parsed; if(tb->tag_value.s && tb->tag_value.len){ totag=tb->tag_value; }else{ totag.s=NULL; totag.len=0; /*if(!(ttag=pkg_malloc(TOTAG_VALUE_LEN))){ LM_ERR("Out of memory !!!\n"); goto error; } totag.s=ttag; calc_crc_suffix(c->uas.request,seas_tag_suffix); LM_DBG("seas_tags = %.*s\n",TOTAG_VALUE_LEN,seas_tags); memcpy(totag.s,seas_tags,TOTAG_VALUE_LEN); totag.len=TOTAG_VALUE_LEN;*/ } LM_DBG("Using totag=[%.*s]\n",totag.len,totag.s); if(my_msg->content_length) contentlength=(unsigned int)(long)my_msg->content_length->parsed; if(0>(i=recordroute_diff(c->uas.request,my_msg))){/*not likely..*/ LM_DBG("Seems that request had more RecordRoutes than response...\n"); /* This prevents host->proxy->host from working. TODO review recordroute_diff code. goto error; */ }else LM_DBG("Recordroute Diff = %d\n",i); if(0>(i=extract_allowed_headers(my_msg,0,i,HDR_VIA_F|HDR_TO_F|HDR_FROM_F|HDR_CSEQ_F|HDR_CALLID_F|HDR_CONTENTLENGTH_F,headers,MAX_HEADER))){ LM_ERR("ac_reply() filtering headers !\n"); goto error; } headers[i]=0; new_header.s=headers; new_header.len=i; /* If it is INVITE and response is success (>=200 && <300), we mark it as local so that * SER does NOT retransmit the final response (by default, SER retransmit local UAS final * responses...*/ if(is_invite(c) && my_msg->first_line.u.reply.statuscode>=200 && my_msg->first_line.u.reply.statuscode<300){ c->flags |= T_IS_LOCAL_FLAG; if(!(the_param=shm_malloc(sizeof(struct as_uac_param)))){ LM_ERR("no more share memory\n"); goto error; } the_param->processor_id=processor_id; the_param->who=my_as; the_param->destroy_cb_set=0; if (seas_f.tmb.register_tmcb( 0, c, TMCB_E2EACK_IN,uas_e2e_ack_cb, the_param,¶m_free)<=0) { LM_ERR("cannot register additional callbacks\n"); goto error; } } /*WARNING casting unsigned int to int*/ body.len=contentlength; body.s=get_body(my_msg); LM_DBG("Trying to construct a SipReply with: ReasonPhrase:[%.*s] body:[%.*s] headers:[%.*s] totag:[%.*s]\n",\ my_msg->first_line.u.reply.reason.len,my_msg->first_line.u.reply.reason.s,\ body.len,body.s,new_header.len,new_header.s,totag.len,totag.s); /* t_reply_with_body un-ref-counts the transaction, so dont use it anymore*/ if(seas_f.tmb.t_reply_with_body(c,my_msg->first_line.u.reply.statuscode,&(my_msg->first_line.u.reply.reason),&body,&new_header,&totag)<0){ LM_ERR("Failed to t_reply\n"); goto error; } retval=0; goto exit; error: retval = -1; if(c) seas_f.tmb.unref_cell(c); if(the_param) shm_free(the_param); exit: if(ttag) pkg_free(ttag); if(my_msg){ free_sip_msg_lite(my_msg); pkg_free(my_msg); } return retval; }
/** * ac_reply: UAS transaction Reply action. It replies to an incoming request with a response. * @param the_as The App Server that sent this action. * @param action action * @param len length * * function description * * Returns: what */ int ac_reply(as_p the_as,char *action,int len) { unsigned int flags,hash_index,label; struct cell *c; struct sip_msg *my_msg; struct to_body *tb; str new_header,body,totag; char *ttag; int i,k,retval; static char headers[MAX_HEADER]; ttag=NULL; my_msg=NULL; i=k=0; net2hostL(flags,action,k); net2hostL(hash_index,action,k); net2hostL(label,action,k); if(seas_f.tmb.t_lookup_ident(&c,hash_index,label)<0){ LM_ERR("Failed to t_lookup_ident hash_idx=%d,label=%d\n",hash_index,label); goto error; } if(use_stats) action_stat(c); if(c->uas.status>=200){ LM_ERR("ac_reply: trying to reply to a \"%.*s\" transaction" "that is already in completed state\n",REQ_LINE(c->uas.request).method.len,REQ_LINE(c->uas.request).method.s); goto error; } if (!(my_msg=parse_ac_msg(HDR_EOH_F,action+k,len-k))) { LM_ERR("Failed to parse_ac_msg hash_idx=%d,label=%d\n",hash_index,label); goto error; } tb=(struct to_body*)my_msg->to->parsed; if(tb->tag_value.s && tb->tag_value.len){ totag=tb->tag_value; }else{ totag.s=NULL; totag.len=0; /*if(!(ttag=pkg_malloc(TOTAG_VALUE_LEN))){ LM_ERR("Out of memory !!!\n"); goto error; } totag.s=ttag; calc_crc_suffix(c->uas.request,seas_tag_suffix); LM_DBG("seas_tags = %.*s\n",TOTAG_VALUE_LEN,seas_tags); memcpy(totag.s,seas_tags,TOTAG_VALUE_LEN); totag.len=TOTAG_VALUE_LEN;*/ } LM_DBG("Using totag=[%.*s]\n",totag.len,totag.s); if(0>(i=recordroute_diff(c->uas.request,my_msg))){/*not likely..*/ LM_DBG("Seems that request had more RecordRoutes than response...\n"); goto error; }else LM_DBG("Recordroute Diff = %d\n",i); if(0>(i=extract_allowed_headers(my_msg,0,i,HDR_VIA_F|HDR_TO_F|HDR_FROM_F|HDR_CSEQ_F|HDR_CALLID_F|HDR_CONTENTLENGTH_F,headers,MAX_HEADER))){ LM_ERR("ac_reply() filtering headers !\n"); goto error; } headers[i]=0; new_header.s=headers; new_header.len=i; /* If it is INVITE and response is success (>=200 && <300), we mark it as local so that * SER does NOT retransmit the final response (by default, SER retransmit local UAS final * responses...*/ if(is_invite(c) && my_msg->first_line.u.reply.statuscode>=200 && my_msg->first_line.u.reply.statuscode<300) c->flags |= T_IS_LOCAL_FLAG; /*WARNING casting unsigned int to int*/ get_body(my_msg, &body); LM_DBG("Trying to construct a SipReply with: ReasonPhrase:[%.*s] body:[%.*s] headers:[%.*s] totag:[%.*s]\n",\ my_msg->first_line.u.reply.reason.len,my_msg->first_line.u.reply.reason.s,\ body.len,body.s,new_header.len,new_header.s,totag.len,totag.s); if(seas_f.tmb.t_reply_with_body(c,my_msg->first_line.u.reply.statuscode, &(my_msg->first_line.u.reply.reason),&body,&new_header,&totag)<0){ LM_ERR("Failed to t_reply\n"); goto error; } seas_f.tmb.unref_cell(c); retval=0; goto exit; error: retval = -1; seas_f.tmb.unref_cell(c); exit: if(ttag) pkg_free(ttag); if(my_msg){ free_sip_msg_lite(my_msg); pkg_free(my_msg); } return retval; }