📄 cpl.c
字号:
for( i=cpl_env.realm_prefix.len-1 ; i>=0 ; i-- ) if ( cpl_env.realm_prefix.s[i]!=((uri->host.s[i])|(0x20)) ) break; if (i==-1) do_strip = 1; } /* calculate the len (without terminating \0) */ uh->len = 4*((flg&BUILD_UH_ADDSIP)!=0) + uri->user.len + 1 + uri->host.len - do_strip*cpl_env.realm_prefix.len; if (flg&BUILD_UH_SHM) { uh->s = (char*)shm_malloc( uh->len + 1 ); if (!uh->s) { LOG(L_ERR,"ERROR:cpl-c:build_userhost: no more shm memory.\n"); return -1; } } else { uh->s = buf; if ( uh->len > MAX_USERHOST_LEN ) { LOG(L_ERR,"ERROR:cpl-c:build_userhost: user+host longer than %d\n", MAX_USERHOST_LEN); return -1; } } /* build user@host */ p = uh->s; if (flg&BUILD_UH_ADDSIP) { memcpy( uh->s, "sip:", 4); p += 4; } /* user part */ if (cpl_env.case_sensitive) { memcpy( p, uri->user.s, uri->user.len); p += uri->user.len; } else { for(i=0;i<uri->user.len;i++) *(p++) = (0x20)|(uri->user.s[i]); } *(p++) = '@'; /* host part in lower cases */ for( i=do_strip*cpl_env.realm_prefix.len ; i< uri->host.len ; i++ ) *(p++) = (0x20)|(uri->host.s[i]); *(p++) = 0; /* sanity check */ if (p-uh->s!=uh->len+1) { LOG(L_CRIT,"BUG:cpl-c:build_userhost: buffer overflow l=%d,w=%ld\n", uh->len,(long)(p-uh->s)); return -1; } return 0;}static inline int get_dest_user(struct sip_msg *msg, str *uh, int flg){ struct sip_uri uri; /* get the user_name from new_uri/RURI/To */ DBG("DEBUG:cpl-c:get_dest_user: trying to get user from new_uri\n"); if ( !msg->new_uri.s || parse_uri( msg->new_uri.s,msg->new_uri.len,&uri)==-1 || !uri.user.len ) { DBG("DEBUG:cpl-c:get_dest_user: trying to get user from R_uri\n"); if ( parse_uri( msg->first_line.u.request.uri.s, msg->first_line.u.request.uri.len ,&uri)==-1 || !uri.user.len ) { DBG("DEBUG:cpl-c:get_dest_user: trying to get user from To\n"); if ( (!msg->to&&( (parse_headers(msg,HDR_TO,0)==-1) || !msg->to))|| parse_uri( get_to(msg)->uri.s, get_to(msg)->uri.len, &uri)==-1 || !uri.user.len) { LOG(L_ERR,"ERROR:cpl-c:get_dest_user: unable to extract user" " name from RURI or To header!\n"); return -1; } } } return build_userhost( &uri, uh, flg);}static inline int get_orig_user(struct sip_msg *msg, str *uh, int flg){ struct to_body *from; struct sip_uri uri; /* if it's outgoing -> get the user_name from From */ /* parsing from header */ DBG("DEBUG:cpl-c:get_orig_user: trying to get user from From\n"); if ( parse_from_header( msg )==-1 ) { LOG(L_ERR,"ERROR:cpl-c:get_orig_user: unable to extract URI " "from FROM header\n"); return -1; } from = (struct to_body*)msg->from->parsed; /* parse the extracted uri from From */ if (parse_uri( from->uri.s, from->uri.len, &uri)||!uri.user.len) { LOG(L_ERR,"ERROR:cpl-c:get_orig_user: unable to extract user name " "from URI (From header)\n"); return -1; } return build_userhost( &uri, uh, flg);}/* Params: * str1 - as unsigned int - can be CPL_RUN_INCOMING or CPL_RUN_OUTGOING * str2 - as unsigned int - flags regarding state(less)|(ful) */static int cpl_invoke_script(struct sip_msg* msg, char* str1, char* str2){ struct cpl_interpreter *cpl_intr; str user; str loc; str script; /* get the user_name */ if ( ((unsigned long)str1)&CPL_RUN_INCOMING ) { /* if it's incoming -> get the destination user name */ if (get_dest_user( msg, &user, BUILD_UH_SHM)==-1) goto error0; } else { /* if it's outgoing -> get the origin user name */ if (get_orig_user( msg, &user, BUILD_UH_SHM)==-1) goto error0; } /* get the script for this user */ if (get_user_script(&user, &script, "cpl_bin")==-1) goto error1; /* has the user a non-empty script? if not, return normally, allowing ser to * continue its script */ if ( !script.s || !script.len ) { shm_free(user.s); return 1; } /* build a new script interpreter */ if ( (cpl_intr=new_cpl_interpreter(msg,&script))==0 ) goto error2; /* set the flags */ cpl_intr->flags =(unsigned int)((unsigned long)str1)|((unsigned long)str2); /* attache the user */ cpl_intr->user = user; /* for OUTGOING we need also the destination user for init. with him * the location set */ if ( ((unsigned long)str1)&CPL_RUN_OUTGOING ) { if (get_dest_user( msg, &loc,BUILD_UH_ADDSIP)==-1) goto error3; if (add_location( &(cpl_intr->loc_set), &loc,10,CPL_LOC_DUPL)==-1) goto error3; } /* since the script interpretation can take some time, it will be better to * send a 100 back to prevent the UAC to retransmit if ( cpl_tmb.t_reply( msg, (int)100, "Running cpl script" )!=1 ) { LOG(L_ERR,"ERROR:cpl_invoke_script: unable to send 100 reply!\n"); goto error3; } * this should be done from script - it's much sooner ;-) */ /* run the script */ switch (cpl_run_script( cpl_intr )) { case SCRIPT_DEFAULT: free_cpl_interpreter( cpl_intr ); return 1; /* execution of ser's script will continue */ case SCRIPT_END: free_cpl_interpreter( cpl_intr ); case SCRIPT_TO_BE_CONTINUED: return 0; /* break the SER script */ case SCRIPT_RUN_ERROR: case SCRIPT_FORMAT_ERROR: goto error3; } return 1;error3: free_cpl_interpreter( cpl_intr ); return -1;error2: shm_free(script.s);error1: shm_free(user.s);error0: return -1;}#define CPL_SCRIPT "script"#define CPL_SCRIPT_LEN (sizeof(CPL_SCRIPT)-1)#define ACTION_PARAM "action"#define ACTION_PARAM_LEN (sizeof(ACTION_PARAM)-1)#define STORE_ACTION "store"#define STORE_ACTION_LEN (sizeof(STORE_ACTION)-1)#define REMOVE_ACTION "remove"#define REMOVE_ACTION_LEN (sizeof(REMOVE_ACTION)-1)#define REMOVE_SCRIPT 0xcaca#define STORE_SCRIPT 0xbebe#define CONTENT_TYPE_HDR ("Content-Type: application/cpl-xml"CRLF)#define CONTENT_TYPE_HDR_LEN (sizeof(CONTENT_TYPE_HDR)-1)struct cpl_error { int err_code; char *err_msg;};static struct cpl_error bad_req = {400,"Bad request"};static struct cpl_error intern_err = {500,"Internal server error"};static struct cpl_error bad_cpl = {400,"Bad CPL script"};static struct cpl_error *cpl_err = &bad_req;static inline int do_script_action(struct sip_msg *msg, int action){ str body = {0,0}; str user = {0,0}; str bin = {0,0}; str log = {0,0}; /* content-length (if present) */ if ( !msg->content_length && ((parse_headers(msg,HDR_CONTENTLENGTH,0)==-1) || !msg->content_length) ) { LOG(L_ERR,"ERROR:cpl-c:do_script_action: no Content-Length " "hdr found!\n"); goto error; } body.len = get_content_length( msg ); /* get the user name */ if (get_dest_user( msg, &user, 0)==-1) goto error; /* we have the script and the user */ switch (action) { case STORE_SCRIPT : /* check the len -> it must not be 0 */ if (body.len==0) { LOG(L_ERR,"ERROR:cpl-c:do_script_action: 0 content-len found " "for store\n"); goto error_1; } /* get the message's body */ body.s = get_body( msg ); if (body.s==0) { LOG(L_ERR,"ERROR:cpl-c:do_script_action: cannot extract " "body from msg!\n"); goto error_1; } /* now compile the script and place it into database */ /* get the binary coding for the XML file */ if ( encodeCPL( &body, &bin, &log)!=1) { cpl_err = &bad_cpl; goto error_1; } /* write both the XML and binary formats into database */ if (write_to_db(user.s, &body, &bin)!=1) { cpl_err = &intern_err; goto error_1; } break; case REMOVE_SCRIPT: /* check the len -> it must be 0 */ if (body.len!=0) { LOG(L_ERR,"ERROR:cpl-c:do_script_action: non-0 content-len " "found for remove\n"); goto error_1; } /* remove the script for the user */ if (rmv_from_db(user.s)!=1) { cpl_err = &intern_err; goto error_1; } break; } if (log.s) pkg_free( log.s ); return 0;error_1: if (log.s) pkg_free( log.s );error: return -1;}static inline int do_script_download(struct sip_msg *msg){ str user = {0,0}; str script = {0,0}; /* get the destination user name */ if (get_dest_user( msg, &user, 0)==-1) goto error; /* get the user's xml script from the database */ if (get_user_script(&user, &script, "cpl_xml")==-1) goto error; /* add a lump with content-type hdr */ if (add_lump_rpl( msg, CONTENT_TYPE_HDR, CONTENT_TYPE_HDR_LEN, LUMP_RPL_HDR)==0) { LOG(L_ERR,"ERROR:cpl-c:do_script_download: cannot build hdr lump\n"); cpl_err = &intern_err; goto error; } if (script.s!=0) { /*DBG("script len=%d\n--------\n%.*s\n--------\n", script.len, script.len, script.s);*/ /* user has a script -> add a body lump */ if ( add_lump_rpl( msg, script.s, script.len, LUMP_RPL_BODY)==0) { LOG(L_ERR,"ERROR:cpl-c:do_script_download: cannot build " "body lump\n"); cpl_err = &intern_err; goto error; } /* build_lump_rpl duplicates the added text, so free the original */ shm_free( script.s ); } return 0;error: if (script.s) shm_free(script.s); return -1;}static int w_process_register(struct sip_msg* msg, char* str, char* str2){ return cpl_process_register( msg, 0);}static int w_process_register_norpl(struct sip_msg* msg, char* str,char* str2){ return cpl_process_register( msg, 1);}static int cpl_process_register(struct sip_msg* msg, int no_rpl){ struct disposition *disp; struct disposition_param *param; int ret; int mime; int *mimes; /* make sure that is a REGISTER ??? */ /* here should be the CONTACT- hack */ /* is there a CONTENT-TYPE hdr ? */ mime = parse_content_type_hdr( msg ); if (mime==-1) goto error; /* check the mime type */ DBG("DEBUG:cpl_process_register: Content-Type mime found %u, %u\n", mime>>16,mime&0x00ff); if ( mime && mime==(TYPE_APPLICATION<<16)+SUBTYPE_CPLXML ) { /* can be an upload or remove -> check for the content-purpose and * content-action headers */ DBG("DEBUG:cpl_process_register: carrying CPL -> look at " "Content-Disposition\n"); if (parse_content_disposition( msg )!=0) { LOG(L_ERR,"ERROR:cpl_process_register: Content-Disposition missing " "or corrupted\n"); goto error; } disp = get_content_disposition(msg); print_disposition( disp ); /* just for DEBUG */ /* check if the type of disposition is SCRIPT */ if (disp->type.len!=CPL_SCRIPT_LEN || strncasecmp(disp->type.s,CPL_SCRIPT,CPL_SCRIPT_LEN) ) { LOG(L_ERR,"ERROR:cpl_process_register: bogus message - Content-Type" "says CPL_SCRIPT, but Content-Disposition something else\n"); goto error; } /* disposition type is OK -> look for action parameter */ for(param=disp->params;param;param=param->next) { if (param->name.len==ACTION_PARAM_LEN && !strncasecmp(param->name.s,ACTION_PARAM,ACTION_PARAM_LEN)) break; } if (param==0) { LOG(L_ERR,"ERROR:cpl_process_register: bogus message - " "Content-Disposition has no action param\n"); goto error; } /* action param found -> check its value: store or remove */ if (param->body.len==STORE_ACTION_LEN && !strncasecmp( param->body.s, STORE_ACTION, STORE_ACTION_LEN)) { /* it's a store action -> get the script from body message and store * it into database (CPL and BINARY format) */ if (do_script_action( msg, STORE_SCRIPT)==-1) goto error; } else if (param->body.len==REMOVE_ACTION_LEN && !strncasecmp( param->body.s, REMOVE_ACTION, REMOVE_ACTION_LEN)) { /* it's a remove action -> remove the script from database */ if (do_script_action( msg, REMOVE_SCRIPT)==-1) goto error; } else { LOG(L_ERR,"ERROR:cpl_process_register: unknown action <%.*s>\n", param->body.len,param->body.s); goto error; } /* do I have to send to reply? */ if (no_rpl) goto resume_script; /* send a 200 OK reply back */ cpl_fct.sl_reply( msg, (char*)200, "OK"); /* I send the reply and I don't want to return to script execution, so * I return 0 to do break */ goto stop_script; } /* is there an ACCEPT hdr ? */ if ( (ret=parse_accept_hdr(msg))==-1) goto error; if (ret==0 || (mimes=get_accept(msg))==0 ) /* accept header not present or no mimes found */ goto resume_script; /* looks if the REGISTER accepts cpl-xml or * */ while (*mimes) { DBG("DEBUG: accept mime found %u, %u\n", (*mimes)>>16,(*mimes)&0x00ff); if (*mimes==(TYPE_ALL<<16)+SUBTYPE_ALL || *mimes==(TYPE_APPLICATION<<16)+SUBTYPE_CPLXML ) break; mimes++; } if (*mimes==0) /* no accept mime that matched cpl */ goto resume_script; /* get the user name from msg, retrieve the script from db * and appended to reply */ if (do_script_download( msg )==-1) goto error; /* do I have to send to reply? */ if (no_rpl) goto resume_script; /* send a 200 OK reply back */ cpl_fct.sl_reply( msg, (char*)200, "OK");stop_script: return 0;resume_script: return 1;error: /* send a error reply back */ cpl_fct.sl_reply( msg, (char*)(long)cpl_err->err_code, cpl_err->err_msg); /* I don't want to return to script execution, so I return 0 to do break */ return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -