주요 파일
파일명 |
기능 | 주요함수 |
receive.c |
socket에서 패킷을 받아서 처리 | receive_msg( ) |
parser/msg_parser.c | socket 에서 받은 패킷에 대해서 SIP protocol 파싱 | parse_msg( ) |
parser/parse_fline.c |
SIP msg 에서 첫줄을 파싱하여 Req/Res 인지 파악 | parse_first_line( ) |
|
|
file: receive.c
/*! \note WARNING: buf must be 0 terminated (buf[len]=0) or some things might
* break (e.g.: modules/textops)
*/
int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info,
context_p existing_context)
{
static context_p ctx = NULL;
struct sip_msg* msg;
struct timeval start;
int rc;
char *tmp;
str in_buff;
in_buff.len = len;
in_buff.s = buf;
if (existing_context) {
context_free(ctx);
ctx = existing_context;
}
/* the raw processing callbacks can change the buffer,
further use in_buff.s and at the end try to free in_buff.s
if changed by callbacks */
if (run_pre_raw_processing_cb(PRE_RAW_PROCESSING,&in_buff,NULL)<0) {
LM_ERR("error in running pre raw callbacks, dropping\n");
goto error;
}
/* update the length for further processing */
len = in_buff.len;
msg=pkg_malloc(sizeof(struct sip_msg));
if (msg==0) {
LM_ERR("no pkg mem left for sip_msg\n");
goto error;
}
msg_no++;
/* number of vias parsed -- good for diagnostic info in replies */
via_cnt=0;
memset(msg,0, sizeof(struct sip_msg)); /* init everything to 0 */
/* fill in msg */
msg->buf=in_buff.s;
msg->len=len;
msg->rcv=*rcv_info;
msg->id=msg_no;
msg->ruri_q = Q_UNSPECIFIED;
if (parse_msg(in_buff.s,len, msg)!=0){
tmp=ip_addr2a(&(rcv_info->src_ip));
LM_ERR("Unable to parse msg received from [%s:%d]\n",
tmp, rcv_info->src_port);
/* if a REQUEST msg was detected (first line was successfully parsed)
we should trigger the error route */
if ( msg->first_line.type==SIP_REQUEST && error_rlist.a!=NULL )
run_error_route(msg, 1);
goto parse_error;
}
LM_DBG("After parse_msg...\n");
start_expire_timer(start,execmsgthreshold);
/* ... clear branches from previous message */
clear_branches();
if (msg->first_line.type==SIP_REQUEST) {
update_stat( rcv_reqs, 1);
/* sanity checks */
if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
/* no via, send back error ? */
LM_ERR("no via found in request\n");
update_stat( err_reqs, 1);
goto parse_error;
}
/* check if necessary to add receive?->moved to forward_req */
/* check for the alias stuff */
if (msg->via1->alias && tcp_accept_aliases &&
is_tcp_based_proto(rcv_info->proto) ) {
if (tcpconn_add_alias(rcv_info->proto_reserved1, msg->via1->port,
rcv_info->proto)!=0){
LM_WARN("tcp alias failed\n");
/* continue */
}
}
LM_DBG("preparing to run routing scripts...\n");
/* set request route type --bogdan*/
set_route_type( REQUEST_ROUTE );
/* prepare and set a new processing context for this request only if
* no context was set from the upper layers */
if (existing_context == NULL)
prepare_context( ctx, parse_error );
current_processing_ctx = ctx;
/* execute pre-script callbacks, if any;
* if some of the callbacks said not to continue with
* script processing, don't do so;
* if we are here basic sanity checks are already done
* (like presence of at least one via), so you can count
* on via1 being parsed in a pre-script callback --andrei
*/
rc = exec_pre_req_cb(msg);
if (rc == SCB_DROP_MSG) {
update_stat( drp_reqs, 1);
goto end; /* drop the message */
}
/* exec the routing script */
if (rc & SCB_RUN_TOP_ROUTE)
/* run the main request route and skip post_script callbacks
* if the TOBE_CONTINUE flag is returned */
if ( run_top_route(rlist[DEFAULT_RT].a, msg) & ACT_FL_TBCONT )
goto end;
/* execute post request-script callbacks */
if (rc & SCB_RUN_POST_CBS)
exec_post_req_cb(msg);
} else if (msg->first_line.type==SIP_REPLY) {
update_stat( rcv_rpls, 1);
/* sanity checks */
if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
/* no via, send back error ? */
LM_ERR("no via found in reply\n");
update_stat( err_rpls, 1);
goto parse_error;
}
/* set reply route type --bogdan*/
set_route_type( ONREPLY_ROUTE );
/* prepare and set a new processing context for this reply only if
* no context was set from the upper layers */
if (existing_context == NULL)
prepare_context( ctx, parse_error );
current_processing_ctx = ctx;
/* execute pre-script callbacks, if any ;
* if some of the callbacks said not to continue with
* script processing, don't do so ;
* if we are here, basic sanity checks are already done
* (like presence of at least one via), so you can count
* on via1 being parsed in a pre-script callback --andrei
*/
rc = exec_pre_rpl_cb(msg);
if (rc == SCB_DROP_MSG) {
update_stat( drp_rpls, 1);
goto end; /* drop the reply */
}
/* exec the onreply routing script */
if (rc & SCB_RUN_TOP_ROUTE && onreply_rlist[DEFAULT_RT].a &&
(run_top_route(onreply_rlist[DEFAULT_RT].a,msg) & ACT_FL_DROP)
&& msg->REPLY_STATUS < 200) {
LM_DBG("dropping provisional reply %d\n", msg->REPLY_STATUS);
update_stat( drp_rpls, 1);
goto end; /* drop the message */
} else {
/* send the msg */
forward_reply(msg);
/* TODO - TX reply stat */
}
/* execute post reply-script callbacks */
if (rc & SCB_RUN_POST_CBS)
exec_post_rpl_cb(msg);
}
end:
/* if someone else set the context, then we should also "release" the
* static ctx. */
if (current_processing_ctx == NULL)
ctx = NULL;
else
context_destroy(CONTEXT_GLOBAL, ctx);
current_processing_ctx = NULL;
stop_expire_timer( start, execmsgthreshold, "msg processing",
msg->buf, msg->len, 0);
reset_longest_action_list(execmsgthreshold);
/* free possible loaded avps -bogdan */
reset_avps();
LM_DBG("cleaning up\n");
free_sip_msg(msg);
pkg_free(msg);
if (in_buff.s != buf)
pkg_free(in_buff.s);
return 0;
parse_error:
exec_parse_err_cb(msg);
free_sip_msg(msg);
pkg_free(msg);
error:
if (in_buff.s != buf)
pkg_free(in_buff.s);
return -1;
}