void test_create_file_at() { char *file = alloc_filename("file"); char *hardlink = alloc_filename("hardlink"); char *hardlink2 = alloc_filename("hardlink2"); int dir_fd = get_dir_fd("."); struct stat st; int fd = openat(dir_fd, file, O_CREAT | O_WRONLY | O_EXCL, 0777); t_check(fd >= 0); t_check_zero(fstat(fd, &st)); t_check_zero(close(fd)); t_check_zero(fstatat(dir_fd, file, &st, 0)); t_check_zero(faccessat(dir_fd, file, R_OK | W_OK, 0)); t_check_zero(fchmodat(dir_fd, file, 0777, 0)); t_check_zero(fchownat(dir_fd, file, -1, -1, 0)); struct timeval times[2] = { { 123, 321 }, { 456, 654 } }; t_check_zero(futimesat(dir_fd, file, times)); t_check_zero(linkat(dir_fd, file, dir_fd, hardlink, 0)); t_check_zero(renameat(dir_fd, hardlink, dir_fd, hardlink2)); t_check_zero(unlinkat(dir_fd, hardlink2, 0)); t_check_zero(unlinkat(dir_fd, file, 0)); close(dir_fd); free(file); free(hardlink); free(hardlink2); }
static int t_flush_flags(struct sip_msg* msg, char *dir, char *foo) { struct cell *t; /* first get the transaction */ if (t_check( msg , 0 )==-1) return -1; if ( (t=get_t())==0) { LOG(L_ERR, "ERROR: t_flush_flags: cannot flush flags for a message " "which has no T-state established\n"); return -1; } /* do the flush */ switch ((long)dir) { case 1: t->uas.request->flags = msg->flags; break; case 2: msg->flags = t->uas.request->flags; break; default: LOG(L_ERR,"ERROR:t_flush_flags: unknown direction %ld\n", (long)dir); return -1; } return 1; }
inline static int w_t_reply(struct sip_msg* msg, char* str, char* str2) { struct cell *t; if (msg->REQ_METHOD==METHOD_ACK) { LOG(L_WARN, "WARNING: t_reply: ACKs are not replied\n"); return -1; } if (t_check( msg , 0 )==-1) return -1; t=get_t(); if (!t) { LOG(L_ERR, "ERROR: t_reply: cannot send a t_reply to a message " "for which no T-state has been established\n"); return -1; } /* if called from reply_route, make sure that unsafe version * is called; we are already in a mutex and another mutex in * the safe version would lead to a deadlock */ if (rmode==MODE_ONFAILURE) { DBG("DEBUG: t_reply_unsafe called from w_t_reply\n"); return t_reply_unsafe(t, msg, (unsigned int)(long) str, str2); } else if (rmode==MODE_REQUEST) { return t_reply( t, msg, (unsigned int)(long) str, str2); } else { LOG(L_CRIT, "BUG: w_t_reply entered in unsupported mode\n"); return -1; } }
void test_create_file() { char *file = alloc_filename("file"); char *hardlink = alloc_filename("hardlink"); char *hardlink2 = alloc_filename("hardlink2"); struct stat st; int fd = open(file, O_CREAT | O_WRONLY | O_EXCL, 0666); t_check(fd >= 0); t_check_zero(fstat(fd, &st)); t_check_zero(close(fd)); t_check_zero(stat(file, &st)); t_check_zero(access(file, R_OK | W_OK)); t_check_zero(chmod(file, 0777)); t_check_zero(chown(file, -1, -1)); struct timeval times[2] = { { 123, 321 }, { 456, 654 } }; t_check_zero(utimes(file, times)); t_check_zero(link(file, hardlink)); t_check_zero(rename(hardlink, hardlink2)); t_check_zero(unlink(hardlink2)); t_check_zero(unlink(file)); free(file); free(hardlink); free(hardlink2); }
static int pv_get_tm_ruri(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) { struct cell *t; if(msg==NULL || res==NULL) return -1; /* first get the transaction */ if (t_check( msg , 0 )==-1) return -1; if ( (t=get_t())==0) { /* no T */ if (msg!=NULL&&msg!=FAKED_REPLY && msg->first_line.type==SIP_REQUEST){ res->rs = *GET_RURI(msg); res->flags = PV_VAL_STR; return 0; } return pv_get_null(msg, param,res); } /* return the RURI for the current branch */ if (_tm_branch_index>=t->nr_of_outgoings) { LM_ERR("BUG: _tm_branch_index greater than nr_of_outgoings\n"); return -1; } res->rs = t->uac[_tm_branch_index].uri; res->flags = PV_VAL_STR; return 0; }
inline static int w_t_reply(struct sip_msg* msg, char* str, char* str2) { struct cell *t; if (msg->REQ_METHOD==METHOD_ACK) { LOG(L_WARN, "WARNING: t_reply: ACKs are not replied\n"); return -1; } if (t_check( msg , 0 )==-1) return -1; t=get_t(); if (!t) { LOG(L_ERR, "ERROR: t_reply: cannot send a t_reply to a message " "for which no T-state has been established\n"); return -1; } /* if called from reply_route, make sure that unsafe version * is called; we are already in a mutex and another mutex in * the safe version would lead to a deadlock */ switch (route_type) { case FAILURE_ROUTE: DBG("DEBUG: t_reply_unsafe called from w_t_reply\n"); return t_reply_unsafe(t, msg, (unsigned int)(long) str, str2); case REQUEST_ROUTE: return t_reply( t, msg, (unsigned int)(long) str, str2); default: LOG(L_CRIT, "BUG:tm:w_t_reply: unsupported route_type (%d)\n", route_type); return -1; } }
inline static int t_local_replied(struct sip_msg* msg, char *all, char *bar) { struct cell *t; int all_rpls; int i; if (t_check( msg , 0 )!=1) { LOG(L_ERR, "ERROR:t_local_replied: no transaction was set up\n"); return -1; } t = get_t(); all_rpls = (int)(long)all; /* is last reply local ? */ if (t->relaied_reply_branch!=-2) return -1; /* were all replies local or none */ if (all_rpls) { for( i=t->first_branch ; i<t->nr_of_outgoings ; i++ ) { if (t->uac[i].flags&T_UAC_HAS_RECV_REPLY) return -1; } } return 1; }
inline static int w_t_release(struct sip_msg* msg, char* str, char* str2) { struct cell *t; if (t_check( msg , 0 )==-1) return -1; t=get_t(); if ( t && t!=T_UNDEFINED ) return t_release_transaction( t ); return 1; }
void test_open_dir_fd() { int fd = open(".", O_RDONLY); t_check(fd >= 0); struct stat st; t_check_zero(fstat(fd, &st)); t_check_zero(fchdir(fd)); t_check_zero(close(fd)); }
/* register a callback function 'f' for 'types' mask of events; * will be called back whenever one of the events occurs in transaction module * (global or per transaction, depending of event type) * It _must_ be always called either with the REPLY_LOCK held, or before the * branches are created. * Special cases: TMCB_REQUEST_IN & TMCB_LOCAL_REQUEST_IN - must be called * from mod_init (before forking!). */ int register_tmcb( struct sip_msg* p_msg, struct cell *t, int types, transaction_cb f, void *param ) { //struct cell* t; struct tmcb_head_list *cb_list; /* are the callback types valid?... */ if ( types<0 || types>TMCB_MAX ) { LOG(L_CRIT, "BUG:tm:register_tmcb: invalid callback types: mask=%d\n", types); return E_BUG; } /* we don't register null functions */ if (f==0) { LOG(L_CRIT, "BUG:tm:register_tmcb: null callback function\n"); return E_BUG; } if (types&TMCB_REQUEST_IN) { if (types!=TMCB_REQUEST_IN) { LOG(L_CRIT, "BUG:tm:register_tmcb: callback type TMCB_REQUEST_IN " "can't be register along with types\n"); return E_BUG; } cb_list = req_in_tmcb_hl; }else if (types & TMCB_LOCAL_REQUEST_IN) { if (types!=TMCB_LOCAL_REQUEST_IN) { LOG(L_CRIT, "BUG:tm:register_tmcb: callback type" " TMCB_LOCAL_REQUEST_IN can't be register along with" " other types\n"); return E_BUG; } cb_list = local_req_in_tmcb_hl; } else { if (!t) { if (!p_msg) { LOG(L_CRIT,"BUG:tm:register_tmcb: no sip_msg, nor transaction" " given\n"); return E_BUG; } /* look for the transaction */ if ( t_check(p_msg,0)!=1 ){ LOG(L_CRIT,"BUG:tm:register_tmcb: no transaction found\n"); return E_BUG; } if ( (t=get_t())==0 ) { LOG(L_CRIT,"BUG:tm:register_tmcb: transaction found " "is NULL\n"); return E_BUG; } } cb_list = &(t->tmcb_hl); } return insert_tmcb( cb_list, types, f, param ); }
void test_readdir() { DIR *dir = opendir("."); t_check(dir != NULL); while(1) { struct dirent *ent = readdir(dir); if(ent == NULL) break; } t_check_zero(closedir(dir)); }
inline static int select_tm_get_cell(struct sip_msg* msg, int *branch, struct cell **t) { /* make sure we know the associated transaction ... */ if (t_check( msg , branch )==-1) /* it's not necessary whan calling from script because already done */ return -1; /*... if there is none, tell the core router to fwd statelessly */ *t = get_t(); if ( (*t==0)||(*t==T_UNDEFINED)) return -1; return 0; }
/**************************** wrapper functions ***************************/ static int t_check_status(struct sip_msg* msg, char *regexp, char *foo) { regmatch_t pmatch; struct cell *t; char *status; char backup; int lowest_status; int n; /* first get the transaction */ if (t_check( msg , 0 )==-1) return -1; if ( (t=get_t())==0) { LOG(L_ERR, "ERROR: t_check_status: cannot check status for a reply " "which has no T-state established\n"); return -1; } backup = 0; switch (route_type) { case REQUEST_ROUTE: /* use the status of the last sent reply */ status = int2str( t->uas.status, 0); break; case ONREPLY_ROUTE: /* use the status of the current reply */ status = msg->first_line.u.reply.status.s; backup = status[msg->first_line.u.reply.status.len]; status[msg->first_line.u.reply.status.len] = 0; break; case FAILURE_ROUTE: /* use the status of the winning reply */ if (t_pick_branch( -1, 0, t, &lowest_status)<0 ) { LOG(L_CRIT,"BUG:t_check_status: t_pick_branch failed to get " " a final response in MODE_ONFAILURE\n"); return -1; } status = int2str( lowest_status , 0); break; default: LOG(L_ERR,"ERROR:t_check_status: unsupported route_type %d\n", route_type); return -1; } DBG("DEBUG:t_check_status: checked status is <%s>\n",status); /* do the checking */ n = regexec((regex_t*)regexp, status, 1, &pmatch, 0); if (backup) status[msg->first_line.u.reply.status.len] = backup; if (n!=0) return -1; return 1; }
static int t_was_cancelled(struct sip_msg* msg, char *foo, char *bar) { struct cell *t; /* first get the transaction */ if (t_check( msg , 0 )==-1) return -1; if ( (t=get_t())==0) { LOG(L_ERR, "ERROR:tm:t_was_cancelled: cannot check cancel flag for " "a reply without a transaction\n"); return -1; } return (t->flags&T_WAS_CANCELLED_FLAG)?1:-1; }
static int pv_get_tm_reply_code(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) { struct cell *t; int code; int branch; if(msg==NULL || res==NULL) return -1; /* first get the transaction */ if (t_check( msg , 0 )==-1) return -1; if ( (t=get_t())==0) { /* no T */ code = 0; } else { switch (route_type) { case REQUEST_ROUTE: /* use the status of the last sent reply */ code = t->uas.status; break; case ONREPLY_ROUTE: /* use the status of the current reply */ code = msg->first_line.u.reply.statuscode; break; case FAILURE_ROUTE: /* use the status of the winning reply */ if ( (branch=t_get_picked_branch())<0 ) { LM_CRIT("no picked branch (%d) for a final response" " in MODE_ONFAILURE\n", branch); code = 0; } else { code = t->uac[branch].last_received; } break; default: LM_ERR("unsupported route_type %d\n", route_type); code = 0; } } LM_DBG("reply code is <%d>\n",code); res->rs.s = int2str( code, &res->rs.len); res->ri = code; res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT; return 0; }
int t_is_local(struct sip_msg* p_msg) { struct cell* t; if(t_check(p_msg,0) != 1){ LOG(L_ERR,"ERROR: t_is_local: no transaction found\n"); return -1; } t = get_t(); if(!t){ LOG(L_ERR,"ERROR: t_is_local: transaction found is NULL\n"); return -1; } return is_local(t); }
inline static int w_t_reply(struct sip_msg* msg, char* p1, char* p2) { struct cell *t; int code, ret = -1; str reason; char* r; if (msg->REQ_METHOD==METHOD_ACK) { LOG(L_WARN, "WARNING: t_reply: ACKs are not replied\n"); return -1; } if (t_check( msg , 0 )==-1) return -1; t=get_t(); if (!t) { LOG(L_ERR, "ERROR: t_reply: cannot send a t_reply to a message " "for which no T-state has been established\n"); return -1; } if (get_int_fparam(&code, msg, (fparam_t*)p1) < 0) { code = default_code; } if (get_str_fparam(&reason, msg, (fparam_t*)p2) < 0) { reason = default_reason; } r = as_asciiz(&reason); if (r == NULL) r = default_reason.s; /* if called from reply_route, make sure that unsafe version * is called; we are already in a mutex and another mutex in * the safe version would lead to a deadlock */ if (rmode==MODE_ONFAILURE) { DBG("DEBUG: t_reply_unsafe called from w_t_reply\n"); ret = t_reply_unsafe(t, msg, code, r); } else if (rmode==MODE_REQUEST) { ret = t_reply( t, msg, code, r); } else { LOG(L_CRIT, "BUG: w_t_reply entered in unsupported mode\n"); ret = -1; } if (r) pkg_free(r); return ret; }
void test_bind() { char *socket_filename = alloc_filename("socket"); int fd; struct sockaddr_un addr; fd = socket(PF_UNIX, SOCK_STREAM, 0); t_check(fd >= 0); addr.sun_family = AF_UNIX; strcpy(addr.sun_path, socket_filename); t_check_zero(bind(fd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un))); t_check_zero(close(fd)); t_check_zero(unlink(socket_filename)); free(socket_filename); }
/* script function, returns: 1 if the transaction was canceled, -1 if not */ int t_is_canceled(struct sip_msg* msg, char* foo, char* bar) { struct cell *t; int ret; if (t_check( msg , 0 )==-1) return -1; t=get_t(); if ((t==0) || (t==T_UNDEFINED)){ LOG(L_ERR, "ERROR: t_is_canceled: cannot check a message " "for which no T-state has been established\n"); ret=-1; }else{ ret=(t->flags & T_CANCELED)?1:-1; } return ret; }
inline static int w_t_retransmit_reply( struct sip_msg* p_msg, char* foo, char* bar) { struct cell *t; if (t_check( p_msg , 0 )==-1) return 1; t=get_t(); if (t) { if (p_msg->REQ_METHOD==METHOD_ACK) { LOG(L_WARN, "WARNING: : ACKs transmit_replies not replied\n"); return -1; } return t_retransmit_reply( t ); } else return -1; }
void test_create_symlink() { char *symlink_filename = alloc_filename("symlink"); const char *dest_path = "dest_path"; t_check_zero(symlink(dest_path, symlink_filename)); char buf[100]; int got; got = readlink(symlink_filename, buf, sizeof(buf)); t_check(got >= 0); assert(got == strlen(dest_path)); buf[got] = 0; assert(strcmp(buf, dest_path) == 0); t_check_zero(unlink(symlink_filename)); free(symlink_filename); }
int t_get_trans_ident(struct sip_msg* p_msg, unsigned int* hash_index, unsigned int* label) { struct cell* t; if(t_check(p_msg,0) != 1){ LOG(L_ERR,"ERROR: t_get_trans_ident: no transaction found\n"); return -1; } t = get_t(); if(!t){ LOG(L_ERR,"ERROR: t_get_trans_ident: transaction found is NULL\n"); return -1; } *hash_index = t->hash_index; *label = t->label; return 1; }
/* script function, returns: 1 if any of the branches received at leat one * reply, -1 if not */ int t_any_replied(struct sip_msg* msg, char* foo, char* bar) { struct cell *t; int r; if (t_check( msg , 0 )==-1) return -1; t=get_t(); if ((t==0) || (t==T_UNDEFINED)){ LOG(L_ERR, "ERROR: t_any_replied: cannot check a message " "for which no T-state has been established\n"); return -1; }else{ for (r=0; r<t->nr_of_outgoings; r++){ if (t->uac[r].request.flags & F_RB_REPLIED) return 1; } } return -1; }
inline static int _w_t_forward_nonack(struct sip_msg* msg, struct proxy_l* proxy, int proto) { struct cell *t; if (t_check( msg , 0 )==-1) { LOG(L_ERR, "ERROR: forward_nonack: " "can't forward when no transaction was set up\n"); return -1; } t=get_t(); if ( t && t!=T_UNDEFINED ) { if (msg->REQ_METHOD==METHOD_ACK) { LOG(L_WARN,"WARNING: you don't really want to fwd hbh ACK\n"); return -1; } return t_forward_nonack(t, msg, proxy, proto ); } else { DBG("DEBUG: forward_nonack: no transaction found\n"); return -1; } }
/* This function is called whenever a reply for our module is received; * we need to register this function on module initialization; * Returns : 0 - core router stops * 1 - core router relay statelessly */ int reply_received( struct sip_msg *p_msg ) { int msg_status; int last_uac_status; int branch; int reply_status; utime_t timer; /* has the transaction completed now and we need to clean-up? */ branch_bm_t cancel_bitmap; struct ua_client *uac; struct cell *t; struct usr_avp **backup_list; unsigned int has_reply_route; set_t(T_UNDEFINED); /* make sure we know the associated transaction ... */ if (t_check(p_msg, &branch ) == -1) goto not_found; /*... if there is none, tell the core router to fwd statelessly */ t = get_t(); if ((t == 0) || (t == T_UNDEFINED)) goto not_found; cancel_bitmap=0; msg_status=p_msg->REPLY_STATUS; uac=&t->uac[branch]; LM_DBG("org. status uas=%d, uac[%d]=%d local=%d is_invite=%d)\n", t->uas.status, branch, uac->last_received, is_local(t), is_invite(t)); last_uac_status=uac->last_received; if_update_stat( tm_enable_stats, tm_rcv_rpls , 1); /* it's a cancel which is not e2e ? */ if ( get_cseq(p_msg)->method_id==METHOD_CANCEL && is_invite(t) ) { /* ... then just stop timers */ reset_timer( &uac->local_cancel.retr_timer); if ( msg_status >= 200 ) { reset_timer( &uac->local_cancel.fr_timer); } LM_DBG("reply to local CANCEL processed\n"); goto done; } /* *** stop timers *** */ /* stop retransmission */ reset_timer(&uac->request.retr_timer); /* stop final response timer only if I got a final response */ if ( msg_status >= 200 ) { reset_timer( &uac->request.fr_timer); } /* acknowledge negative INVITE replies (do it before detailed * on_reply processing, which may take very long, like if it * is attempted to establish a TCP connection to a fail-over dst */ if (is_invite(t) && ((msg_status >= 300) || (is_local(t) && !no_autoack(t) && msg_status >= 200) )) { if (send_ack(p_msg, t, branch)!=0) LM_ERR("failed to send ACK (local=%s)\n", is_local(t)?"yes":"no"); } _tm_branch_index = branch; /* processing of on_reply block */ has_reply_route = (t->on_reply) || (t->uac[branch].on_reply); if (has_reply_route) { if (onreply_avp_mode) { /* lock the reply*/ LOCK_REPLIES( t ); /* set the as avp_list the one from transaction */ backup_list = set_avp_list(&t->user_avps); } else { backup_list = 0; } /* transfer transaction flag to branch context */ p_msg->flags = t->uas.request->flags; setb0flags(t->uac[branch].br_flags); /* run block - first per branch and then global one */ if ( t->uac[branch].on_reply && (run_top_route(onreply_rlist[t->uac[branch].on_reply].a,p_msg) &ACT_FL_DROP) && (msg_status<200) ) { if (onreply_avp_mode) { UNLOCK_REPLIES( t ); set_avp_list( backup_list ); } LM_DBG("dropping provisional reply %d\n", msg_status); goto done; } if ( t->on_reply && (run_top_route(onreply_rlist[t->on_reply].a,p_msg) &ACT_FL_DROP) && (msg_status<200) ) { if (onreply_avp_mode) { UNLOCK_REPLIES( t ); set_avp_list( backup_list ); } LM_DBG("dropping provisional reply %d\n", msg_status); goto done; } /* transfer current message context back to t */ t->uac[branch].br_flags = getb0flags(); t->uas.request->flags = p_msg->flags; if (onreply_avp_mode) /* restore original avp list */ set_avp_list( backup_list ); } if (!onreply_avp_mode || !has_reply_route) /* lock the reply*/ LOCK_REPLIES( t ); /* mark that the UAC received replies */ uac->flags |= T_UAC_HAS_RECV_REPLY; /* we fire a cancel on spot if (a) branch is marked "to be canceled" or (b) * the whole transaction was canceled (received cancel) and no cancel sent * yet on this branch; and of course, only if a provisional reply :) */ if (t->uac[branch].flags&T_UAC_TO_CANCEL_FLAG || ((t->flags&T_WAS_CANCELLED_FLAG) && !t->uac[branch].local_cancel.buffer.s)) { if ( msg_status < 200 ) /* reply for an UAC with a pending cancel -> do cancel now */ cancel_branch(t, branch); /* reset flag */ t->uac[branch].flags &= ~(T_UAC_TO_CANCEL_FLAG); } if (is_local(t)) { reply_status = local_reply(t,p_msg, branch,msg_status,&cancel_bitmap); if (reply_status == RPS_COMPLETED) { cleanup_uac_timers(t); if (is_invite(t)) cancel_uacs(t, cancel_bitmap); /* There is no need to call set_final_timer because we know * that the transaction is local */ put_on_wait(t); } } else { reply_status = relay_reply(t,p_msg,branch,msg_status,&cancel_bitmap); /* clean-up the transaction when transaction completed */ if (reply_status == RPS_COMPLETED) { /* no more UAC FR/RETR (if I received a 2xx, there may * be still pending branches ... */ cleanup_uac_timers(t); if (is_invite(t)) cancel_uacs(t, cancel_bitmap); /* FR for negative INVITES, WAIT anything else */ /* set_final_timer(t); */ } } if (reply_status!=RPS_PROVISIONAL) goto done; /* update FR/RETR timers on provisional replies */ if (msg_status < 200 && (restart_fr_on_each_reply || ((last_uac_status<msg_status) && ((msg_status >= 180) || (last_uac_status == 0))) ) ) { /* provisional now */ if (is_invite(t)) { /* invite: change FR to longer FR_INV, do not * attempt to restart retransmission any more */ backup_list = set_avp_list(&t->user_avps); if (!fr_inv_avp2timer(&timer)) { LM_DBG("FR_INV_TIMER = %lld\n", timer); set_timer(&uac->request.fr_timer, FR_INV_TIMER_LIST, &timer); } else { set_timer(& uac->request.fr_timer, FR_INV_TIMER_LIST, 0); } set_avp_list(backup_list); } else { /* non-invite: restart retransmissions (slow now) */ uac->request.retr_list = RT_T2; set_timer(&uac->request.retr_timer, RT_T2, 0); } } /* provisional replies */ done: /* we are done with the transaction, so unref it - the reference * was incremented by t_check() function -bogdan*/ t_unref(p_msg); /* don't try to relay statelessly neither on success * (we forwarded statefully) nor on error; on troubles, * simply do nothing; that will make the other party to * retransmit; hopefuly, we'll then be better off */ _tm_branch_index = 0; return 0; not_found: set_t(T_UNDEFINED); return 1; }
/* Suspends the transaction for later use. * Save the returned hash_index and label to get * back to the SIP request processing, see the readme. * * Return value: * 0 - success * <0 - failure */ int t_suspend(struct sip_msg *msg, unsigned int *hash_index, unsigned int *label) { struct cell *t; int branch; int sip_msg_len; t = get_t(); if (!t || t == T_UNDEFINED) { LM_ERR("transaction has not been created yet\n"); return -1; } if (t->flags & T_CANCELED) { /* The transaction has already been canceled */ LM_DBG("trying to suspend an already canceled transaction\n"); ser_error = E_CANCELED; return 1; } if (t->uas.status >= 200) { LM_DBG("trasaction sent out a final response already - %d\n", t->uas.status); return -3; } if (msg->first_line.type != SIP_REPLY) { /* send a 100 Trying reply, because the INVITE processing will probably take a long time */ if (msg->REQ_METHOD==METHOD_INVITE && (t->flags&T_AUTO_INV_100) && (t->uas.status < 100) ) { if (!t_reply( t, msg , 100 , cfg_get(tm, tm_cfg, tm_auto_inv_100_r))) LM_DBG("suspending request processing - sending 100 reply\n"); } if ((t->nr_of_outgoings==0) && /* if there had already been an UAC created, then the lumps were saved as well */ save_msg_lumps(t->uas.request, msg) ) { LM_ERR("failed to save the message lumps\n"); return -1; } /* save the message flags */ t->uas.request->flags = msg->flags; /* add a blind UAC to let the fr timer running */ if (add_blind_uac() < 0) { LM_ERR("failed to add the blind UAC\n"); return -1; } /* propagate failure route to new branch * - failure route to be executed if the branch is not continued * before timeout */ t->uac[t->async_backup.blind_uac].on_failure = t->on_failure; t->flags |= T_ASYNC_SUSPENDED; } else { LM_DBG("this is a suspend on reply - setting msg flag to SUSPEND\n"); msg->msg_flags |= FL_RPL_SUSPENDED; /* this is a reply suspend find which branch */ if (t_check( msg , &branch )==-1){ LOG(L_ERR, "ERROR: t_suspend_reply: " \ "failed find UAC branch\n"); return -1; } LM_DBG("found a a match with branch id [%d] - " "cloning reply message to t->uac[branch].reply\n", branch); sip_msg_len = 0; t->uac[branch].reply = sip_msg_cloner( msg, &sip_msg_len ); if (! t->uac[branch].reply ) { LOG(L_ERR, "can't alloc' clone memory\n"); return -1; } t->uac[branch].end_reply = ((char*)t->uac[branch].reply) + sip_msg_len; LM_DBG("saving transaction data\n"); t->uac[branch].reply->flags = msg->flags; t->flags |= T_ASYNC_SUSPENDED; } *hash_index = t->hash_index; *label = t->label; /* backup some extra info that can be used in continuation logic */ t->async_backup.backup_route = get_route_type(); t->async_backup.backup_branch = get_t_branch(); t->async_backup.ruri_new = ruri_get_forking_state(); return 0; }
void test_getcwd() { char *str = getcwd(NULL, 0); t_check(str != NULL); free(str); }
inline static int w_t_check(struct sip_msg* msg, char* str, char* str2) { return t_check( msg , 0 ) ? 1 : -1; }