R&D/RCS

OpenSIPS receive 함수

sunshout 2017. 11. 22. 13:17

주요 파일

파일명 

 기능

 주요함수

 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;
}