⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpl.c

📁 用来作为linux中SIP SERVER,完成VOIP网络电话中服务器的功能
💻 C
📖 第 1 页 / 共 2 页
字号:
		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 + -