📄 cpl_run.c
字号:
} for( i=NR_OF_ATTR(intr->ip),p=ATTR_PTR(intr->ip) ; i>0 ; i-- ) { get_basic_attr( p, attr_name, n, intr, script_error); switch (attr_name) { case STATUS_ATTR: status = n; break; case REASON_ATTR: get_str_attr( p, reason_s, n, intr, script_error,1); break; default: LOG(L_ERR,"ERROR:cpl_c:run_reject: unknown attribute " "(%d) in REJECT node\n",attr_name); goto script_error; } } if (status==UNDEF_CHAR) { LOG(L_ERR,"ERROR:cpl_c:run_reject: mandatory attribute STATUS " "not found\n"); goto script_error; } if (status<400 || status>=700) { LOG(L_ERR,"ERROR:cpl_c:run_reject: bad attribute STATUS " "(%d)\n",status); goto script_error; } if (reason_s==(char*)UNDEF_CHAR ) { switch (status) { case 486: reason_s = "Busy Here"; break; case 404: reason_s = "Not Found"; break; case 603: reason_s = "Decline"; break; case 500: reason_s = "Internal Server Error"; break; default: reason_s = "Generic Error"; } } /* if still stateless and FORCE_STATEFUL set -> build the transaction */ if ( !(intr->flags&CPL_IS_STATEFUL) && intr->flags&CPL_FORCE_STATEFUL) { i = cpl_fct.tmb.t_newtran( intr->msg ); if (i<0) { LOG(L_ERR,"ERROR:cpl-c:run_reject: failed to build new " "transaction!\n"); goto runtime_error; } else if (i==0) { LOG(L_ERR,"ERROR:cpl-c:run_reject: processed INVITE is a " "retransmission!\n"); /* instead of generating an error is better just to break the * script by returning EO_SCRIPT */ return EO_SCRIPT; } intr->flags |= CPL_IS_STATEFUL; } /* send the reply */ if ( intr->flags&CPL_IS_STATEFUL ) { /* reply statefully */ i = cpl_fct.tmb.t_reply(intr->msg, (int)status, reason_s ); } else { /* reply statelessly */ i = cpl_fct.sl_reply(intr->msg, (char*)(long)status, reason_s ); } if ( i!=1 ) { LOG(L_ERR,"ERROR:run_reject: unable to send reject reply!\n"); goto runtime_error; } return EO_SCRIPT;runtime_error: return CPL_RUNTIME_ERROR;script_error: return CPL_SCRIPT_ERROR;}/* UPDATED + CHECKED */static inline char *run_redirect( struct cpl_interpreter *intr ){ struct location *loc; struct lump_rpl *lump; unsigned short attr_name; unsigned short permanent; unsigned short n; char *p; str lump_str; char *cp; int i; permanent = NO_VAL; /* sanity check */ if (NR_OF_KIDS(intr->ip)!=0) { LOG(L_ERR,"ERROR:cpl-c:run_redirect: REDIRECT node doesn't suppose " "to have any sub-nodes. Found %d!\n",NR_OF_KIDS(intr->ip)); goto script_error; } /* read the attributes of the REDIRECT node*/ for( i=NR_OF_ATTR(intr->ip),p=ATTR_PTR(intr->ip) ; i>0 ; i-- ) { get_basic_attr( p, attr_name, n, intr, script_error); switch (attr_name) { case PERMANENT_ATTR: if (n!=YES_VAL && n!=NO_VAL) { LOG(L_ERR,"ERROR:cpl-c:run_redirect: unsupported value (%d)" " in attribute PERMANENT for REDIRECT node",n); goto script_error; } permanent = n; break; default: LOG(L_ERR,"ERROR:run_redirect: unknown attribute " "(%d) in REDIRECT node\n",attr_name); goto script_error; } } /* build the lump for Contact header */ lump_str.len = 9 /*"Contact: "*/; for(loc=intr->loc_set;loc;loc=loc->next) lump_str.len += 1/*"<"*/ + loc->addr.uri.len + 7/*">;q=x.x"*/ + 2*(loc->next!=0)/*" ,"*/; lump_str.len += CRLF_LEN; lump_str.s = pkg_malloc( lump_str.len ); if(!lump_str.s) { LOG(L_ERR,"ERROR:cpl-c:run_redirect: out of pkg memory!\n"); goto runtime_error; } cp = lump_str.s; memcpy( cp , "Contact: " , 9); cp += 9; for(loc=intr->loc_set;loc;loc=loc->next) { *(cp++) = '<'; memcpy(cp,loc->addr.uri.s,loc->addr.uri.len); cp += loc->addr.uri.len; memcpy(cp,">;q=",4); cp += 4; *(cp++) = (loc->addr.priority!=10)?'0':'1'; *(cp++) = '.'; *(cp++) = '0'+(loc->addr.priority%10); if (loc->next) { *(cp++) = ' '; *(cp++) = ','; } } memcpy(cp,CRLF,CRLF_LEN); /* if still stateless and FORCE_STATEFUL set -> build the transaction */ if ( !(intr->flags&CPL_IS_STATEFUL) && intr->flags&CPL_FORCE_STATEFUL) { i = cpl_fct.tmb.t_newtran( intr->msg ); if (i<0) { LOG(L_ERR,"ERROR:cpl-c:run_redirect: failed to build new " "transaction!\n"); pkg_free( lump_str.s ); goto runtime_error; } else if (i==0) { LOG(L_ERR,"ERROR:cpl-c:run_redirect: processed INVITE is a " "retransmission!\n"); /* instead of generating an error is better just to break the * script by returning EO_SCRIPT */ pkg_free( lump_str.s ); return EO_SCRIPT; } intr->flags |= CPL_IS_STATEFUL; } /* add the lump to the reply */ lump = add_lump_rpl( intr->msg, lump_str.s , lump_str.len , LUMP_RPL_HDR); if(!lump) { LOG(L_ERR,"ERROR:cpl-c:run_redirect: unable to add lump_rpl! \n"); pkg_free( lump_str.s ); goto runtime_error; } /* send the reply */ if ( intr->flags&CPL_IS_STATEFUL ) { /* reply statefully */ if (permanent) i = cpl_fct.tmb.t_reply( intr->msg, (int)301, "Moved permanently"); else i = cpl_fct.tmb.t_reply( intr->msg, (int)302, "Moved temporarily"); } else { /* reply statelessly */ if (permanent) i = cpl_fct.sl_reply( intr->msg, (char*)301, "Moved permanently"); else i = cpl_fct.sl_reply( intr->msg, (char*)302, "Moved temporarily"); } /* msg which I'm working on can be in private memory or is a clone into * shared memory (if I'm after a failed proxy); So, it's better to removed * by myself the lump that I added previously */ unlink_lump_rpl( intr->msg, lump); free_lump_rpl( lump ); if (i!=1) { LOG(L_ERR,"ERROR:cpl-c:run_redirect: unable to send " "redirect reply!\n"); goto runtime_error; } return EO_SCRIPT;runtime_error: return CPL_RUNTIME_ERROR;script_error: return CPL_SCRIPT_ERROR;}/* UPDATED + CHECKED */static inline char *run_log( struct cpl_interpreter *intr ){ char *p; unsigned short attr_name; unsigned short n; str name = {0,0}; str comment = {0,0}; str user; int i; /* sanity check */ if (NR_OF_KIDS(intr->ip)>1) { LOG(L_ERR,"ERROR:cpl_c:run_log: LOG node suppose to have max one child" ", not %d!\n",NR_OF_KIDS(intr->ip)); goto script_error; } /* is logging enabled? */ if ( cpl_env.log_dir==0 ) goto done; /* read the attributes of the LOG node*/ p = ATTR_PTR(intr->ip); for( i=NR_OF_ATTR(intr->ip); i>0 ; i-- ) { get_basic_attr( p, attr_name, n, intr, script_error); switch (attr_name) { case NAME_ATTR: get_str_attr( p, name.s, n, intr, script_error,1); name.len = n; break; case COMMENT_ATTR: get_str_attr( p, comment.s, n, intr, script_error,1); comment.len = n; break; default: LOG(L_ERR,"ERROR:cpl_c:run_log: unknown attribute " "(%d) in LOG node\n",attr_name); goto script_error; } } if (comment.len==0) { LOG(L_NOTICE,"NOTICE:cpl_c:run_log: LOG node has no comment attr -> " "skipping\n"); goto done; } user.len = intr->user.len + name.len + comment.len; /* duplicate the attrs in shm memory */ user.s = p = (char*)shm_malloc( user.len ); if (!user.s) { LOG(L_ERR,"ERROR:cpl_c:run_log: no more shm memory!\n"); goto runtime_error; } /* copy the user name */ memcpy( p, intr->user.s, intr->user.len); user.len = intr->user.len; p += intr->user.len; /* copy the log name */ if (name.len) { memcpy( p, name.s, name.len ); name.s = p; p += name.len; } /* copy the comment */ memcpy( p, comment.s, comment.len); comment.s = p; /* send the command */ write_cpl_cmd( CPL_LOG_CMD, &user, &name, &comment );done: return get_first_child(intr->ip);runtime_error: return CPL_RUNTIME_ERROR;script_error: return CPL_SCRIPT_ERROR;}/* UPDATED + CHECKED */static inline char *run_mail( struct cpl_interpreter *intr ){ unsigned short attr_name; unsigned short n; char *p; str subject = {0,0}; str body = {0,0}; str to = {0,0}; int i; /* sanity check */ if (NR_OF_KIDS(intr->ip)>1) { LOG(L_ERR,"ERROR:cpl_c:run_mail: MAIL node suppose to have max one" " child, not %d!\n",NR_OF_KIDS(intr->ip)); goto script_error; } /* read the attributes of the MAIL node*/ for( i=NR_OF_ATTR(intr->ip),p=ATTR_PTR(intr->ip) ; i>0 ; i-- ) { get_basic_attr(p, attr_name, n, intr, script_error); switch (attr_name) { case TO_ATTR: get_str_attr(p, to.s, n, intr, script_error,0); to.len = n; break; case SUBJECT_ATTR: get_str_attr(p, subject.s, n, intr, script_error,0); subject.len = n; break; case BODY_ATTR: get_str_attr(p, body.s, n, intr, script_error,0); body.len = n; break; default: LOG(L_ERR,"ERROR:run_mail: unknown attribute " "(%d) in MAIL node\n",attr_name); goto script_error; } } if (to.len==0) { LOG(L_ERR,"ERROR:cpl_c:run_mail: email has an empty TO hdr!\n"); goto script_error; } if (body.len==0 && subject.len==0) { LOG(L_WARN,"WARNING:cpl_c:run_mail: I refuse to send email with no " "body and no subject -> skipping...\n"); goto done; } /* duplicate the attrs in shm memory */ p = (char*)shm_malloc( to.len + subject.len + body.len ); if (!p) { LOG(L_ERR,"ERROR:cpl_c:run_mail: no more shm memory!\n"); goto runtime_error; } /* copy the TO */ memcpy( p, to.s, to.len ); to.s = p; p += to.len; /* copy the subject */ if (subject.len) { memcpy( p, subject.s, subject.len ); subject.s = p; p += subject.len; } /* copy the body */ if (body.len) { memcpy( p, body.s, body.len ); body.s = p; p += body.len; } /* send the command */ write_cpl_cmd( CPL_MAIL_CMD, &to, &subject, &body);done: return get_first_child(intr->ip);runtime_error: return CPL_RUNTIME_ERROR;script_error: return CPL_SCRIPT_ERROR;}static inline int run_default( struct cpl_interpreter *intr ){ if (!(intr->flags&CPL_PROXY_DONE)) { /* no signaling operations */ if ( !(intr->flags&CPL_LOC_SET_MODIFIED) ) { /* no location modifications */ if (intr->loc_set==0 ) { /* case 1 : no location modifications or signaling operations * performed, location set empty -> * Look up the user's location through whatever mechanism the * server would use if no CPL script were in effect */ return SCRIPT_DEFAULT; } else { /* case 2 : no location modifications or signaling operations * performed, location set non-empty: (This can only happen * for outgoing calls.) -> * Proxy the call to the address in the location set. * With other words, let ser to continue processing the * request as nothing happened */ return SCRIPT_DEFAULT; } } else { /* case 3 : location modifications performed, no signaling * operations -> * Proxy the call to the addresses in the location set */ if (!cpl_proxy_to_loc_set(intr->msg,&(intr->loc_set),intr->flags)) return SCRIPT_END; return SCRIPT_RUN_ERROR; } } else { /* case 4 : proxy operation previously taken -> return whatever the * "best" response is of all accumulated responses to the call to this * point, according to the rules of the underlying signaling * protocol. */ /* we will let ser to choose and forward one of the replies -> for this * nothing must be done */ return SCRIPT_END; } /*return SCRIPT_RUN_ERROR;*/}/* include all inline functions for processing the switches */#include "cpl_switches.h"/* include inline function for running proxy node */#include "cpl_proxy.h"int cpl_run_script( struct cpl_interpreter *intr ){ char *new_ip; do { check_overflow_by_offset( SIMPLE_NODE_SIZE(intr->ip), intr, error); switch ( NODE_TYPE(intr->ip) ) { case CPL_NODE: DBG("DEBUG:cpl_run_script: processing CPL node \n"); new_ip = run_cpl_node( intr ); /*UPDATED&TESTED*/ break; case ADDRESS_SWITCH_NODE: DBG("DEBUG:cpl_run_script: processing address-switch node\n"); new_ip = run_address_switch( intr ); /*UPDATED&TESTED*/ break; case STRING_SWITCH_NODE: DBG("DEBUG:cpl_run_script: processing string-switch node\n"); new_ip = run_string_switch( intr ); /*UPDATED&TESTED*/ break; case PRIORITY_SWITCH_NODE: DBG("DEBUG:cpl_run_script: processing priority-switch node\n"); new_ip = run_priority_switch( intr ); /*UPDATED&TESTED*/ break; case TIME_SWITCH_NODE: DBG("DEBUG:cpl_run_script: processing time-switch node\n"); new_ip = run_time_switch( intr ); /*UPDATED&TESTED*/ break; case LANGUAGE_SWITCH_NODE: DBG("DEBUG:cpl_run_script: processing language-switch node\n"); new_ip = run_language_switch( intr ); /*UPDATED&TESTED*/ break; case LOOKUP_NODE: DBG("DEBUG:cpl_run_script: processing lookup node\n"); new_ip = run_lookup( intr ); /*UPDATED&TESTED*/ break; case LOCATION_NODE: DBG("DEBUG:cpl_run_script: processing location node\n"); new_ip = run_location( intr ); /*UPDATED&TESTED*/ break; case REMOVE_LOCATION_NODE: DBG("DEBUG:cpl_run_script: processing remove_location node\n"); new_ip = run_remove_location( intr ); /*UPDATED&TESTED*/ break; case PROXY_NODE: DBG("DEBUG:cpl_run_script: processing proxy node\n"); new_ip = run_proxy( intr );/*UPDATED&TESTED*/ break; case REJECT_NODE: DBG("DEBUG:cpl_run_script: processing reject node\n"); new_ip = run_reject( intr ); /*UPDATED&TESTED*/ break; case REDIRECT_NODE: DBG("DEBUG:cpl_run_script: processing redirect node\n"); new_ip = run_redirect( intr ); /*UPDATED&TESTED*/ break; case LOG_NODE: DBG("DEBUG:cpl_run_script: processing log node\n"); new_ip = run_log( intr ); /*UPDATED&TESTED*/ break; case MAIL_NODE: DBG("DEBUG:cpl_run_script: processing mail node\n"); new_ip = run_mail( intr ); /*UPDATED&TESTED*/ break; case SUB_NODE: DBG("DEBUG:cpl_run_script: processing sub node\n"); new_ip = run_sub( intr ); /*UPDATED&TESTED*/ break; default: LOG(L_ERR,"ERROR:cpl_run_script: unknown type node (%d)\n", NODE_TYPE(intr->ip)); goto error; } if (new_ip==CPL_RUNTIME_ERROR) { LOG(L_ERR,"ERROR:cpl_c:cpl_run_script: runtime error\n"); return SCRIPT_RUN_ERROR; } else if (new_ip==CPL_SCRIPT_ERROR) { LOG(L_ERR,"ERROR:cpl_c:cpl_run_script: script error\n"); return SCRIPT_FORMAT_ERROR; } else if (new_ip==DEFAULT_ACTION) { DBG("DEBUG:cpl_c:cpl_run_script: running default action\n"); return run_default(intr); } else if (new_ip==EO_SCRIPT) { DBG("DEBUG:cpl_c:cpl_run_script: script interpretation done!\n"); return SCRIPT_END; } else if (new_ip==CPL_TO_CONTINUE) { DBG("DEBUG:cpl_c:cpl_run_script: done for the moment; waiting " "after signaling!\n"); return SCRIPT_TO_BE_CONTINUED; } /* move to the new instruction */ intr->ip = new_ip; }while(1);error: return SCRIPT_FORMAT_ERROR;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -