|
@@ -41,6 +41,7 @@
|
|
* 2003-03-16 removed _TOTAG (jiri)
|
|
* 2003-03-16 removed _TOTAG (jiri)
|
|
* 2003-03-31 200 for INVITE/UAS resent even for UDP (jiri)
|
|
* 2003-03-31 200 for INVITE/UAS resent even for UDP (jiri)
|
|
* 2003-03-31 removed msg->repl_add_rm (andrei)
|
|
* 2003-03-31 removed msg->repl_add_rm (andrei)
|
|
|
|
+ * 2003-04-05 s/reply_route/failure_route, onreply_route introduced (jiri)
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
|
|
@@ -82,6 +83,8 @@ static char *tm_tag_suffix;
|
|
|
|
|
|
/* where to go if there is no positive reply */
|
|
/* where to go if there is no positive reply */
|
|
static int goto_on_negative=0;
|
|
static int goto_on_negative=0;
|
|
|
|
+/* where to go on receipt of reply */
|
|
|
|
+static int goto_on_reply=0;
|
|
|
|
|
|
|
|
|
|
/* we store the reply_route # in private memory which is
|
|
/* we store the reply_route # in private memory which is
|
|
@@ -94,10 +97,14 @@ static int goto_on_negative=0;
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
|
|
-int t_on_negative( unsigned int go_to )
|
|
|
|
|
|
+void t_on_negative( unsigned int go_to )
|
|
{
|
|
{
|
|
goto_on_negative=go_to;
|
|
goto_on_negative=go_to;
|
|
- return 1;
|
|
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void t_on_reply( unsigned int go_to )
|
|
|
|
+{
|
|
|
|
+ goto_on_reply=go_to;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -105,6 +112,10 @@ unsigned int get_on_negative()
|
|
{
|
|
{
|
|
return goto_on_negative;
|
|
return goto_on_negative;
|
|
}
|
|
}
|
|
|
|
+unsigned int get_on_reply()
|
|
|
|
+{
|
|
|
|
+ return goto_on_reply;
|
|
|
|
+}
|
|
|
|
|
|
void tm_init_tags()
|
|
void tm_init_tags()
|
|
{
|
|
{
|
|
@@ -141,6 +152,16 @@ int unmatched_totag(struct cell *t, struct sip_msg *ack)
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static inline void update_local_tags(struct cell *trans,
|
|
|
|
+ struct bookmark *bm, char *dst_buffer,
|
|
|
|
+ char *src_buffer /* to which bm refers */)
|
|
|
|
+{
|
|
|
|
+ if (bm->to_tag_val.s) {
|
|
|
|
+ trans->uas.local_totag.s=bm->to_tag_val.s-src_buffer+dst_buffer;
|
|
|
|
+ trans->uas.local_totag.len=bm->to_tag_val.len;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
|
|
/* append a newly received tag from a 200/INVITE to
|
|
/* append a newly received tag from a 200/INVITE to
|
|
* transaction's set; (only safe if called from within
|
|
* transaction's set; (only safe if called from within
|
|
@@ -213,6 +234,141 @@ static char *build_ack(struct sip_msg* rpl,struct cell *trans,int branch,
|
|
ACK, ACK_LEN, &to );
|
|
ACK, ACK_LEN, &to );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int _reply_light( struct cell *trans, char* buf, unsigned int len,
|
|
|
|
+ unsigned int code, char * text,
|
|
|
|
+ char *to_tag, unsigned int to_tag_len, int lock,
|
|
|
|
+ struct bookmark *bm )
|
|
|
|
+{
|
|
|
|
+ struct retr_buf *rb;
|
|
|
|
+ unsigned int buf_len;
|
|
|
|
+ branch_bm_t cancel_bitmap;
|
|
|
|
+
|
|
|
|
+ if (!buf)
|
|
|
|
+ {
|
|
|
|
+ DBG("DEBUG: t_reply: response building failed\n");
|
|
|
|
+ /* determine if there are some branches to be cancelled */
|
|
|
|
+ if (trans->is_invite) {
|
|
|
|
+ if (lock) LOCK_REPLIES( trans );
|
|
|
|
+ which_cancel(trans, &cancel_bitmap );
|
|
|
|
+ if (lock) UNLOCK_REPLIES( trans );
|
|
|
|
+ }
|
|
|
|
+ /* and clean-up, including cancellations, if needed */
|
|
|
|
+ goto error;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ cancel_bitmap=0;
|
|
|
|
+ if (lock) LOCK_REPLIES( trans );
|
|
|
|
+ if (trans->is_invite) which_cancel(trans, &cancel_bitmap );
|
|
|
|
+ if (trans->uas.status>=200) {
|
|
|
|
+ LOG( L_ERR, "ERROR: t_reply: can't generate %d reply"
|
|
|
|
+ " when a final %d was sent out\n", code, trans->uas.status);
|
|
|
|
+ goto error2;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ rb = & trans->uas.response;
|
|
|
|
+ rb->activ_type=code;
|
|
|
|
+
|
|
|
|
+ trans->uas.status = code;
|
|
|
|
+ buf_len = rb->buffer ? len : len + REPLY_OVERBUFFER_LEN;
|
|
|
|
+ rb->buffer = (char*)shm_resize( rb->buffer, buf_len );
|
|
|
|
+ /* puts the reply's buffer to uas.response */
|
|
|
|
+ if (! rb->buffer ) {
|
|
|
|
+ LOG(L_ERR, "ERROR: t_reply: cannot allocate shmem buffer\n");
|
|
|
|
+ goto error3;
|
|
|
|
+ }
|
|
|
|
+ update_local_tags(trans, bm, rb->buffer, buf);
|
|
|
|
+
|
|
|
|
+ rb->buffer_len = len ;
|
|
|
|
+ memcpy( rb->buffer , buf , len );
|
|
|
|
+ /* needs to be protected too because what timers are set depends
|
|
|
|
+ on current transactions status */
|
|
|
|
+ /* t_update_timers_after_sending_reply( rb ); */
|
|
|
|
+ update_reply_stats( code );
|
|
|
|
+ trans->relaied_reply_branch=-2;
|
|
|
|
+ tm_stats->replied_localy++;
|
|
|
|
+ if (lock) UNLOCK_REPLIES( trans );
|
|
|
|
+
|
|
|
|
+ /* do UAC cleanup procedures in case we generated
|
|
|
|
+ a final answer whereas there are pending UACs */
|
|
|
|
+ if (code>=200) {
|
|
|
|
+ if (trans->local) {
|
|
|
|
+ DBG("DEBUG: local transaction completed from _reply\n");
|
|
|
|
+ callback_event( TMCB_LOCAL_COMPLETED, trans, FAKED_REPLY, code );
|
|
|
|
+ if (trans->completion_cb)
|
|
|
|
+ trans->completion_cb( trans, FAKED_REPLY, code, 0 /* empty param */);
|
|
|
|
+ } else {
|
|
|
|
+ callback_event( TMCB_RESPONSE_OUT, trans, FAKED_REPLY, code );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ cleanup_uac_timers( trans );
|
|
|
|
+ if (trans->is_invite) cancel_uacs( trans, cancel_bitmap );
|
|
|
|
+ set_final_timer( trans );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* send it out */
|
|
|
|
+ /* first check if we managed to resolve topmost Via -- if
|
|
|
|
+ not yet, don't try to retransmit
|
|
|
|
+ */
|
|
|
|
+ if (!trans->uas.response.dst.send_sock) {
|
|
|
|
+ LOG(L_ERR, "ERROR: _reply: no resolved dst to send reply to\n");
|
|
|
|
+ } else {
|
|
|
|
+ SEND_PR_BUFFER( rb, buf, len );
|
|
|
|
+ DBG("DEBUG: reply sent out. buf=%p: %.9s..., shmem=%p: %.9s\n",
|
|
|
|
+ buf, buf, rb->buffer, rb->buffer );
|
|
|
|
+ }
|
|
|
|
+ pkg_free( buf ) ;
|
|
|
|
+ DBG("DEBUG: t_reply: finished\n");
|
|
|
|
+ return 1;
|
|
|
|
+
|
|
|
|
+error3:
|
|
|
|
+error2:
|
|
|
|
+ if (lock) UNLOCK_REPLIES( trans );
|
|
|
|
+ pkg_free ( buf );
|
|
|
|
+error:
|
|
|
|
+ /* do UAC cleanup */
|
|
|
|
+ cleanup_uac_timers( trans );
|
|
|
|
+ if (trans->is_invite) cancel_uacs( trans, cancel_bitmap );
|
|
|
|
+ /* we did not succeed -- put the transaction on wait */
|
|
|
|
+ put_on_wait(trans);
|
|
|
|
+ return -1;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+/* send a UAS reply
|
|
|
|
+ * returns 1 if everything was OK or -1 for error
|
|
|
|
+ */
|
|
|
|
+static int _reply( struct cell *trans, struct sip_msg* p_msg,
|
|
|
|
+ unsigned int code, char * text, int lock )
|
|
|
|
+{
|
|
|
|
+ unsigned int len;
|
|
|
|
+ char * buf;
|
|
|
|
+ struct bookmark bm;
|
|
|
|
+
|
|
|
|
+ if (code>=200) set_kr(REQ_RPLD);
|
|
|
|
+ /* compute the buffer in private memory prior to entering lock;
|
|
|
|
+ * create to-tag if needed */
|
|
|
|
+ if (code>=180 && p_msg->to
|
|
|
|
+ && (get_to(p_msg)->tag_value.s==0
|
|
|
|
+ || get_to(p_msg)->tag_value.len==0)) {
|
|
|
|
+ calc_crc_suffix( p_msg, tm_tag_suffix );
|
|
|
|
+ buf = build_res_buf_from_sip_req(code,text,
|
|
|
|
+ tm_tags, TOTAG_VALUE_LEN,
|
|
|
|
+ p_msg,&len, &bm);
|
|
|
|
+
|
|
|
|
+ return _reply_light(trans,buf,len,code,text,
|
|
|
|
+ tm_tags, TOTAG_VALUE_LEN,
|
|
|
|
+ lock, &bm);
|
|
|
|
+ } else {
|
|
|
|
+ buf = build_res_buf_from_sip_req(code,text, 0,0, /* no to-tag */
|
|
|
|
+ p_msg,&len, &bm);
|
|
|
|
+
|
|
|
|
+ return _reply_light(trans,buf,len,code,text,
|
|
|
|
+ 0,0, /* no to-tag */
|
|
|
|
+ lock, &bm);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
|
|
/* create a temporary faked message environment in which a conserved
|
|
/* create a temporary faked message environment in which a conserved
|
|
* t->uas.request in shmem is partially duplicated to pkgmem
|
|
* t->uas.request in shmem is partially duplicated to pkgmem
|
|
@@ -257,7 +413,7 @@ static int faked_env(struct sip_msg *fake,
|
|
* for example t_reply needs to know that
|
|
* for example t_reply needs to know that
|
|
*/
|
|
*/
|
|
backup_mode=rmode;
|
|
backup_mode=rmode;
|
|
- rmode=MODE_ONREPLY_REQUEST;
|
|
|
|
|
|
+ rmode=MODE_ONFAILURE;
|
|
/* also, tm actions look in beginning whether tranaction is
|
|
/* also, tm actions look in beginning whether tranaction is
|
|
* set -- whether we are called from a reply-processing
|
|
* set -- whether we are called from a reply-processing
|
|
* or a timer process, we need to set current transaction;
|
|
* or a timer process, we need to set current transaction;
|
|
@@ -309,11 +465,68 @@ restore:
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/* return 1 if a failure_route processes */
|
|
|
|
+int failure_route(struct cell *t)
|
|
|
|
+{
|
|
|
|
+ struct sip_msg faked_msg;
|
|
|
|
+
|
|
|
|
+ /* don't do anything if we don't have to */
|
|
|
|
+ if (!t->on_negative) return 0;
|
|
|
|
+
|
|
|
|
+ /* if fake message creation failes, return error too */
|
|
|
|
+ if (!faked_env(&faked_msg, t, t->uas.request, 0 /* create fake */ )) {
|
|
|
|
+ LOG(L_ERR, "ERROR: on_negative_reply: faked_env failed\n");
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* avoid recursion -- if failure_route forwards, and does not
|
|
|
|
+ * set next failure route, failure_route will not be rentered
|
|
|
|
+ * on failure */
|
|
|
|
+ t_on_negative(0);
|
|
|
|
+ /* run a reply_route action if some was marked */
|
|
|
|
+ if (run_actions(failure_rlist[t->on_negative], &faked_msg)<0)
|
|
|
|
+ LOG(L_ERR, "ERROR: on_negative_reply: "
|
|
|
|
+ "Error in do_action\n");
|
|
|
|
+ /* restore original environment */
|
|
|
|
+ faked_env(&faked_msg, 0, 0, 1 );
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
|
|
|
|
|
|
-/* the main code of stateful replying */
|
|
|
|
-static int _reply( struct cell *t, struct sip_msg* p_msg, unsigned int code,
|
|
|
|
- char * text, int lock );
|
|
|
|
|
|
+/* select a branch for forwarding; returns:
|
|
|
|
+ * 0..X ... branch number
|
|
|
|
+ * -1 ... error
|
|
|
|
+ * -2 ... can't decide yet -- incomplete branches present
|
|
|
|
+ */
|
|
|
|
+static int pick_branch( int inc_branch, int inc_code,
|
|
|
|
+ struct cell *t, int *res_code)
|
|
|
|
+{
|
|
|
|
+ int lowest_b, lowest_s, b;
|
|
|
|
+
|
|
|
|
+ lowest_b=-1; lowest_s=999;
|
|
|
|
+ for ( b=0; b<t->nr_of_outgoings ; b++ ) {
|
|
|
|
+ /* "fake" for the currently processed branch */
|
|
|
|
+ if (b==inc_branch) {
|
|
|
|
+ if (inc_code<lowest_s) {
|
|
|
|
+ lowest_b=b;
|
|
|
|
+ lowest_s=inc_code;
|
|
|
|
+ }
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ /* skip 'empty branches' */
|
|
|
|
+ if (!t->uac[b].request.buffer) continue;
|
|
|
|
+ /* there is still an unfinished UAC transaction; wait now! */
|
|
|
|
+ if ( t->uac[b].last_received<200 )
|
|
|
|
+ return -2;
|
|
|
|
+ if ( t->uac[b].last_received<lowest_s ) {
|
|
|
|
+ lowest_b =b;
|
|
|
|
+ lowest_s = t->uac[b].last_received;
|
|
|
|
+ }
|
|
|
|
+ } /* find lowest branch */
|
|
|
|
+
|
|
|
|
+ *res_code=lowest_s;
|
|
|
|
+ return lowest_b;
|
|
|
|
+}
|
|
|
|
|
|
/* This is the neuralgical point of reply processing -- called
|
|
/* This is the neuralgical point of reply processing -- called
|
|
* from within a REPLY_LOCK, t_should_relay_response decides
|
|
* from within a REPLY_LOCK, t_should_relay_response decides
|
|
@@ -330,9 +543,10 @@ static enum rps t_should_relay_response( struct cell *Trans , int new_code,
|
|
int branch , int *should_store, int *should_relay,
|
|
int branch , int *should_store, int *should_relay,
|
|
branch_bm_t *cancel_bitmap, struct sip_msg *reply )
|
|
branch_bm_t *cancel_bitmap, struct sip_msg *reply )
|
|
{
|
|
{
|
|
- int b, lowest_b, lowest_s, dummy;
|
|
|
|
- struct sip_msg faked_msg, *origin_rq;
|
|
|
|
- unsigned int on_neg;
|
|
|
|
|
|
+
|
|
|
|
+ int branch_cnt;
|
|
|
|
+ int picked_branch;
|
|
|
|
+ int picked_code;
|
|
|
|
|
|
/* note: this code never lets replies to CANCEL go through;
|
|
/* note: this code never lets replies to CANCEL go through;
|
|
we generate always a local 200 for CANCEL; 200s are
|
|
we generate always a local 200 for CANCEL; 200s are
|
|
@@ -378,63 +592,31 @@ static enum rps t_should_relay_response( struct cell *Trans , int new_code,
|
|
}
|
|
}
|
|
|
|
|
|
Trans->uac[branch].last_received=new_code;
|
|
Trans->uac[branch].last_received=new_code;
|
|
|
|
+
|
|
|
|
+
|
|
/* if all_final return lowest */
|
|
/* if all_final return lowest */
|
|
- lowest_b=-1; lowest_s=999;
|
|
|
|
- for ( b=0; b<Trans->nr_of_outgoings ; b++ ) {
|
|
|
|
- /* "fake" for the currently processed branch */
|
|
|
|
- if (b==branch) {
|
|
|
|
- if (new_code<lowest_s) {
|
|
|
|
- lowest_b=b;
|
|
|
|
- lowest_s=new_code;
|
|
|
|
- }
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
- /* skip 'empty branches' */
|
|
|
|
- if (!Trans->uac[b].request.buffer) continue;
|
|
|
|
- /* there is still an unfinished UAC transaction; wait now! */
|
|
|
|
- if ( Trans->uac[b].last_received<200 ) {
|
|
|
|
- *should_store=1;
|
|
|
|
- *should_relay=-1;
|
|
|
|
- return RPS_STORE;
|
|
|
|
- }
|
|
|
|
- if ( Trans->uac[b].last_received<lowest_s )
|
|
|
|
- {
|
|
|
|
- lowest_b =b;
|
|
|
|
- lowest_s = Trans->uac[b].last_received;
|
|
|
|
- }
|
|
|
|
- } /* find lowest branch */
|
|
|
|
- if (lowest_b==-1) {
|
|
|
|
|
|
+ picked_branch=pick_branch(branch,new_code, Trans, &picked_code);
|
|
|
|
+ if (picked_branch==-2) { /* branches open yet */
|
|
|
|
+ *should_store=1;
|
|
|
|
+ *should_relay=-1;
|
|
|
|
+ return RPS_STORE;
|
|
|
|
+ }
|
|
|
|
+ if (picked_branch==-1) {
|
|
LOG(L_CRIT, "ERROR: t_should_relay_response: lowest==-1\n");
|
|
LOG(L_CRIT, "ERROR: t_should_relay_response: lowest==-1\n");
|
|
|
|
+ goto error;
|
|
}
|
|
}
|
|
|
|
+
|
|
/* no more pending branches -- try if that changes after
|
|
/* no more pending branches -- try if that changes after
|
|
- a callback
|
|
|
|
|
|
+ a callback; save banch count to be able to determine
|
|
|
|
+ later if new branches were initiated
|
|
*/
|
|
*/
|
|
|
|
+ branch_cnt=Trans->nr_of_outgoings;
|
|
callback_event( TMCB_ON_FAILURE, Trans,
|
|
callback_event( TMCB_ON_FAILURE, Trans,
|
|
- lowest_b==branch?reply:Trans->uac[lowest_b].reply,
|
|
|
|
- lowest_s );
|
|
|
|
-
|
|
|
|
|
|
+ picked_branch==branch?reply:Trans->uac[picked_branch].reply,
|
|
|
|
+ picked_code);
|
|
/* here, we create a faked environment, from which we
|
|
/* here, we create a faked environment, from which we
|
|
* return to request processing, if marked to do so */
|
|
* return to request processing, if marked to do so */
|
|
- origin_rq=Trans->uas.request;
|
|
|
|
- on_neg=Trans->on_negative;
|
|
|
|
- if (on_neg) {
|
|
|
|
- DBG("DBG: on_negative_reply processed for transaction %p\n",
|
|
|
|
- Trans);
|
|
|
|
- if (faked_env(&faked_msg, Trans, Trans->uas.request,
|
|
|
|
- 0 /* create fake */ ))
|
|
|
|
- {
|
|
|
|
- /* use the faked message later in forwarding */
|
|
|
|
- origin_rq=&faked_msg;
|
|
|
|
- /* run a reply_route action if some was marked */
|
|
|
|
- if (run_actions(reply_rlist[on_neg], &faked_msg )<0)
|
|
|
|
- LOG(L_ERR, "ERROR: on_negative_reply: "
|
|
|
|
- "Error in do_action\n");
|
|
|
|
- } else { /* faked_env creation error */
|
|
|
|
- LOG(L_ERR, "ERROR: on_negative_reply: faked_env failed\n");
|
|
|
|
- on_neg=0;
|
|
|
|
- }
|
|
|
|
- } /* if (on_neg) */
|
|
|
|
-
|
|
|
|
|
|
+ failure_route(Trans);
|
|
|
|
|
|
/* look if the callback perhaps replied transaction; it also
|
|
/* look if the callback perhaps replied transaction; it also
|
|
covers the case in which a transaction is replied localy
|
|
covers the case in which a transaction is replied localy
|
|
@@ -450,34 +632,19 @@ static enum rps t_should_relay_response( struct cell *Trans , int new_code,
|
|
put it on wait again; perhaps splitting put_on_wait
|
|
put it on wait again; perhaps splitting put_on_wait
|
|
from send_reply or a new RPS_ code would be healthy
|
|
from send_reply or a new RPS_ code would be healthy
|
|
*/
|
|
*/
|
|
- if (on_neg) faked_env(&faked_msg, 0, 0, 1 );
|
|
|
|
return RPS_COMPLETED;
|
|
return RPS_COMPLETED;
|
|
}
|
|
}
|
|
- /* look if the callback introduced new branches ... */
|
|
|
|
- init_branch_iterator();
|
|
|
|
- if (next_branch(&dummy)) {
|
|
|
|
- if (t_forward_nonack(Trans, origin_rq,
|
|
|
|
- (struct proxy_l *) 0,
|
|
|
|
- Trans->uas.response.dst.proto)<0) {
|
|
|
|
- /* error ... behave as if we did not try to
|
|
|
|
- add a new branch */
|
|
|
|
- *should_store=0;
|
|
|
|
- *should_relay=lowest_b;
|
|
|
|
- if (on_neg) faked_env(&faked_msg, 0, 0, 1 );
|
|
|
|
- return RPS_COMPLETED;
|
|
|
|
- }
|
|
|
|
- /* we succeded to launch new branches -- await
|
|
|
|
- result
|
|
|
|
- */
|
|
|
|
|
|
+ /* look if the callback/failure_route introduced new branches ... */
|
|
|
|
+ if (branch_cnt<Trans->nr_of_outgoings) {
|
|
|
|
+ /* await then result of new branches */
|
|
*should_store=1;
|
|
*should_store=1;
|
|
*should_relay=-1;
|
|
*should_relay=-1;
|
|
- if (on_neg) faked_env(&faked_msg, 0, 0, 1 );
|
|
|
|
return RPS_STORE;
|
|
return RPS_STORE;
|
|
}
|
|
}
|
|
|
|
+
|
|
/* really no more pending branches -- return lowest code */
|
|
/* really no more pending branches -- return lowest code */
|
|
*should_store=0;
|
|
*should_store=0;
|
|
- *should_relay=lowest_b;
|
|
|
|
- if (on_neg) faked_env(&faked_msg, 0, 0, 1 );
|
|
|
|
|
|
+ *should_relay=picked_branch;
|
|
/* we dont need 'which_cancel' here -- all branches
|
|
/* we dont need 'which_cancel' here -- all branches
|
|
known to have completed */
|
|
known to have completed */
|
|
/* which_cancel( Trans, cancel_bitmap ); */
|
|
/* which_cancel( Trans, cancel_bitmap ); */
|
|
@@ -496,6 +663,7 @@ static enum rps t_should_relay_response( struct cell *Trans , int new_code,
|
|
} else return RPS_PROVISIONAL;
|
|
} else return RPS_PROVISIONAL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+error:
|
|
/* reply_status didn't match -- it must be something weird */
|
|
/* reply_status didn't match -- it must be something weird */
|
|
LOG(L_CRIT, "ERROR: Oh my gooosh! We don't know whether to relay %d\n",
|
|
LOG(L_CRIT, "ERROR: Oh my gooosh! We don't know whether to relay %d\n",
|
|
new_code);
|
|
new_code);
|
|
@@ -567,150 +735,8 @@ int t_reply_unsafe( struct cell *t, struct sip_msg* p_msg, unsigned int code,
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-static inline void update_local_tags(struct cell *trans,
|
|
|
|
- struct bookmark *bm, char *dst_buffer,
|
|
|
|
- char *src_buffer /* to which bm refers */)
|
|
|
|
-{
|
|
|
|
- if (bm->to_tag_val.s) {
|
|
|
|
- trans->uas.local_totag.s=bm->to_tag_val.s-src_buffer+dst_buffer;
|
|
|
|
- trans->uas.local_totag.len=bm->to_tag_val.len;
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-static int _reply_light( struct cell *trans, char* buf, unsigned int len,
|
|
|
|
- unsigned int code, char * text,
|
|
|
|
- char *to_tag, unsigned int to_tag_len, int lock,
|
|
|
|
- struct bookmark *bm )
|
|
|
|
-{
|
|
|
|
- struct retr_buf *rb;
|
|
|
|
- unsigned int buf_len;
|
|
|
|
- branch_bm_t cancel_bitmap;
|
|
|
|
-
|
|
|
|
- if (!buf)
|
|
|
|
- {
|
|
|
|
- DBG("DEBUG: t_reply: response building failed\n");
|
|
|
|
- /* determine if there are some branches to be cancelled */
|
|
|
|
- if (trans->is_invite) {
|
|
|
|
- if (lock) LOCK_REPLIES( trans );
|
|
|
|
- which_cancel(trans, &cancel_bitmap );
|
|
|
|
- if (lock) UNLOCK_REPLIES( trans );
|
|
|
|
- }
|
|
|
|
- /* and clean-up, including cancellations, if needed */
|
|
|
|
- goto error;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- cancel_bitmap=0;
|
|
|
|
- if (lock) LOCK_REPLIES( trans );
|
|
|
|
- if (trans->is_invite) which_cancel(trans, &cancel_bitmap );
|
|
|
|
- if (trans->uas.status>=200) {
|
|
|
|
- LOG( L_ERR, "ERROR: t_reply: can't generate %d reply"
|
|
|
|
- " when a final %d was sent out\n", code, trans->uas.status);
|
|
|
|
- goto error2;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
|
|
|
|
- rb = & trans->uas.response;
|
|
|
|
- rb->activ_type=code;
|
|
|
|
|
|
|
|
- trans->uas.status = code;
|
|
|
|
- buf_len = rb->buffer ? len : len + REPLY_OVERBUFFER_LEN;
|
|
|
|
- rb->buffer = (char*)shm_resize( rb->buffer, buf_len );
|
|
|
|
- /* puts the reply's buffer to uas.response */
|
|
|
|
- if (! rb->buffer ) {
|
|
|
|
- LOG(L_ERR, "ERROR: t_reply: cannot allocate shmem buffer\n");
|
|
|
|
- goto error3;
|
|
|
|
- }
|
|
|
|
- update_local_tags(trans, bm, rb->buffer, buf);
|
|
|
|
-
|
|
|
|
- rb->buffer_len = len ;
|
|
|
|
- memcpy( rb->buffer , buf , len );
|
|
|
|
- /* needs to be protected too because what timers are set depends
|
|
|
|
- on current transactions status */
|
|
|
|
- /* t_update_timers_after_sending_reply( rb ); */
|
|
|
|
- update_reply_stats( code );
|
|
|
|
- trans->relaied_reply_branch=-2;
|
|
|
|
- tm_stats->replied_localy++;
|
|
|
|
- if (lock) UNLOCK_REPLIES( trans );
|
|
|
|
-
|
|
|
|
- /* do UAC cleanup procedures in case we generated
|
|
|
|
- a final answer whereas there are pending UACs */
|
|
|
|
- if (code>=200) {
|
|
|
|
- if (trans->local) {
|
|
|
|
- DBG("DEBUG: local transaction completed from _reply\n");
|
|
|
|
- callback_event( TMCB_LOCAL_COMPLETED, trans, FAKED_REPLY, code );
|
|
|
|
- if (trans->completion_cb)
|
|
|
|
- trans->completion_cb( trans, FAKED_REPLY, code, 0 /* empty param */);
|
|
|
|
- } else {
|
|
|
|
- callback_event( TMCB_RESPONSE_OUT, trans, FAKED_REPLY, code );
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- cleanup_uac_timers( trans );
|
|
|
|
- if (trans->is_invite) cancel_uacs( trans, cancel_bitmap );
|
|
|
|
- set_final_timer( trans );
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* send it out */
|
|
|
|
- /* first check if we managed to resolve topmost Via -- if
|
|
|
|
- not yet, don't try to retransmit
|
|
|
|
- */
|
|
|
|
- if (!trans->uas.response.dst.send_sock) {
|
|
|
|
- LOG(L_ERR, "ERROR: _reply: no resolved dst to send reply to\n");
|
|
|
|
- } else {
|
|
|
|
- SEND_PR_BUFFER( rb, buf, len );
|
|
|
|
- DBG("DEBUG: reply sent out. buf=%p: %.9s..., shmem=%p: %.9s\n",
|
|
|
|
- buf, buf, rb->buffer, rb->buffer );
|
|
|
|
- }
|
|
|
|
- pkg_free( buf ) ;
|
|
|
|
- DBG("DEBUG: t_reply: finished\n");
|
|
|
|
- return 1;
|
|
|
|
-
|
|
|
|
-error3:
|
|
|
|
-error2:
|
|
|
|
- if (lock) UNLOCK_REPLIES( trans );
|
|
|
|
- pkg_free ( buf );
|
|
|
|
-error:
|
|
|
|
- /* do UAC cleanup */
|
|
|
|
- cleanup_uac_timers( trans );
|
|
|
|
- if (trans->is_invite) cancel_uacs( trans, cancel_bitmap );
|
|
|
|
- /* we did not succeed -- put the transaction on wait */
|
|
|
|
- put_on_wait(trans);
|
|
|
|
- return -1;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/* send a UAS reply
|
|
|
|
- * returns 1 if everything was OK or -1 for error
|
|
|
|
- */
|
|
|
|
-static int _reply( struct cell *trans, struct sip_msg* p_msg,
|
|
|
|
- unsigned int code, char * text, int lock )
|
|
|
|
-{
|
|
|
|
- unsigned int len;
|
|
|
|
- char * buf;
|
|
|
|
- struct bookmark bm;
|
|
|
|
-
|
|
|
|
- if (code>=200) set_kr(REQ_RPLD);
|
|
|
|
- /* compute the buffer in private memory prior to entering lock;
|
|
|
|
- * create to-tag if needed */
|
|
|
|
- if (code>=180 && p_msg->to
|
|
|
|
- && (get_to(p_msg)->tag_value.s==0
|
|
|
|
- || get_to(p_msg)->tag_value.len==0)) {
|
|
|
|
- calc_crc_suffix( p_msg, tm_tag_suffix );
|
|
|
|
- buf = build_res_buf_from_sip_req(code,text,
|
|
|
|
- tm_tags, TOTAG_VALUE_LEN,
|
|
|
|
- p_msg,&len, &bm);
|
|
|
|
-
|
|
|
|
- return _reply_light(trans,buf,len,code,text,
|
|
|
|
- tm_tags, TOTAG_VALUE_LEN,
|
|
|
|
- lock, &bm);
|
|
|
|
- } else {
|
|
|
|
- buf = build_res_buf_from_sip_req(code,text, 0,0, /* no to-tag */
|
|
|
|
- p_msg,&len, &bm);
|
|
|
|
-
|
|
|
|
- return _reply_light(trans,buf,len,code,text,
|
|
|
|
- 0,0, /* no to-tag */
|
|
|
|
- lock, &bm);
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
|
|
|
|
void set_final_timer( /* struct s_table *h_table, */ struct cell *t )
|
|
void set_final_timer( /* struct s_table *h_table, */ struct cell *t )
|
|
{
|
|
{
|
|
@@ -1017,7 +1043,7 @@ error:
|
|
* Returns : 0 - core router stops
|
|
* Returns : 0 - core router stops
|
|
* 1 - core router relay statelessly
|
|
* 1 - core router relay statelessly
|
|
*/
|
|
*/
|
|
-int t_on_reply( struct sip_msg *p_msg )
|
|
|
|
|
|
+int reply_received( struct sip_msg *p_msg )
|
|
{
|
|
{
|
|
|
|
|
|
int msg_status;
|
|
int msg_status;
|
|
@@ -1068,6 +1094,13 @@ int t_on_reply( struct sip_msg *p_msg )
|
|
if ( msg_status >= 200 )
|
|
if ( msg_status >= 200 )
|
|
reset_timer( &uac->request.fr_timer);
|
|
reset_timer( &uac->request.fr_timer);
|
|
|
|
|
|
|
|
+ /* processing of on_reply block */
|
|
|
|
+ if (t->on_reply) {
|
|
|
|
+ rmode=MODE_ONREPLY;
|
|
|
|
+ if (run_actions(onreply_rlist[t->on_reply], p_msg)<0)
|
|
|
|
+ LOG(L_ERR, "ERROR: on_reply processing failed\n");
|
|
|
|
+ }
|
|
|
|
+
|
|
LOCK_REPLIES( t );
|
|
LOCK_REPLIES( t );
|
|
if (t->local) {
|
|
if (t->local) {
|
|
reply_status=local_reply( t, p_msg, branch, msg_status, &cancel_bitmap );
|
|
reply_status=local_reply( t, p_msg, branch, msg_status, &cancel_bitmap );
|