Changeset 4275


Ignore:
Timestamp:
Oct 4, 2012 6:11:58 AM (12 years ago)
Author:
bennylp
Message:

Close #1590: APIs to facilitate pending processing of pjsip_rx_data

Location:
pjproject/trunk/pjsip
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/include/pjsip/sip_endpoint.h

    r4154 r4275  
    214214                                                    pjsip_module *module ); 
    215215 
     216/** 
     217 * This describes additional parameters to pjsip_endpt_process_rx_data() 
     218 * function. Application MUST call pjsip_process_rdata_param_default() to 
     219 * initialize this structure. 
     220 */ 
     221typedef struct pjsip_process_rdata_param 
     222{ 
     223    /** 
     224     * Specify the minimum priority number of the modules that are allowed 
     225     * to process the message. Default is zero to allow all modules to 
     226     * process the message. 
     227     */ 
     228    unsigned start_prio; 
     229 
     230    /** 
     231     * Specify the pointer of the module where processing will start. 
     232     * The default is NULL, meaning processing will start from the start 
     233     * of the module list. 
     234     */ 
     235    void *start_mod; 
     236 
     237    /** 
     238     * Set to N, then processing will start at Nth module after start 
     239     * module (where start module can be an explicit module as specified 
     240     * by \a start_mod or the start of module list when \a start_mod is 
     241     * NULL). For example, if set to 1, then processing will start from 
     242     * the next module after start module. Default is zero. 
     243     */ 
     244    unsigned idx_after_start; 
     245 
     246    /** 
     247     * Print nothing to log. Default is PJ_FALSE. 
     248     */ 
     249    pj_bool_t silent; 
     250 
     251} pjsip_process_rdata_param; 
     252 
     253/** 
     254 * Initialize with default. 
     255 * 
     256 * @param p     The param. 
     257 */ 
     258PJ_DECL(void) pjsip_process_rdata_param_default(pjsip_process_rdata_param *p); 
     259 
     260/** 
     261 * Manually distribute the specified pjsip_rx_data to registered modules. 
     262 * Normally application does not need to call this function because received 
     263 * messages will be given to endpoint automatically by transports. 
     264 * 
     265 * Application can use this function when it has postponed the processing of 
     266 * an incoming message, for example to perform long operations such as 
     267 * database operation or to consult other servers to decide what to do with 
     268 * the message. In this case, application clones the original rdata, return 
     269 * from the callback, and perform the long operation. Upon completing the 
     270 * long operation, it resumes pjsip's module processing by calling this 
     271 * function, and then free the cloned rdata. 
     272 * 
     273 * @param endpt         The endpoint instance. 
     274 * @param rdata         The rdata to be distributed. 
     275 * @param p             Optional pointer to param to specify from which module 
     276 *                      the processing should start. 
     277 * @param p_handled     Optional pointer to receive last return value of 
     278 *                      module's \a on_rx_request() or \a on_rx_response() 
     279 *                      callback. 
     280 * 
     281 * @return              PJ_SUCCESS on success. 
     282 */ 
     283PJ_DECL(pj_status_t) pjsip_endpt_process_rx_data(pjsip_endpoint *endpt, 
     284                                                 pjsip_rx_data *rdata, 
     285                                                 pjsip_process_rdata_param *p, 
     286                                                 pj_bool_t *p_handled); 
    216287 
    217288/** 
  • pjproject/trunk/pjsip/include/pjsip/sip_transport.h

    r4218 r4275  
    427427 */ 
    428428PJ_DECL(char*) pjsip_rx_data_get_info(pjsip_rx_data *rdata); 
     429 
     430/** 
     431 * Clone pjsip_rx_data. This will duplicate the contents of 
     432 * pjsip_rx_data and add reference count to the transport. 
     433 * Once application has finished using the cloned pjsip_rx_data, 
     434 * it must release it by calling  #pjsip_rx_data_free_cloned(). 
     435 * 
     436 * By default (if flags is set to zero), this function copies the 
     437 * transport pointer in \a tp_info, duplicates the \a pkt_info, 
     438 * perform deep clone of the \a msg_info parts of the rdata, and 
     439 * fills the \a endpt_info (i.e. the \a mod_data) with zeros. 
     440 * 
     441 * @param src       The source to be cloned. 
     442 * @param flags     Optional flags. Must be zero for now. 
     443 * @param p_rdata   Pointer to receive the cloned rdata. 
     444 * 
     445 * @return          PJ_SUCCESS on success or the appropriate error. 
     446 */ 
     447PJ_DECL(pj_status_t) pjsip_rx_data_clone(const pjsip_rx_data *src, 
     448                                         unsigned flags, 
     449                                         pjsip_rx_data **p_rdata); 
     450 
     451/** 
     452 * Free cloned pjsip_rx_data. This function must be and must only 
     453 * be called for a cloned pjsip_rx_data. Specifically, it must NOT 
     454 * be called for the original pjsip_rx_data that is returned by 
     455 * transports. 
     456 * 
     457 * This function will free the memory used by the pjsip_rx_data and 
     458 * decrement the transport reference counter. 
     459 * 
     460 * @param rdata     The receive data buffer. 
     461 * 
     462 * @return          PJ_SUCCESS on success or the appropriate error. 
     463 */ 
     464PJ_DECL(pj_status_t) pjsip_rx_data_free_cloned(pjsip_rx_data *rdata); 
    429465 
    430466 
  • pjproject/trunk/pjsip/src/pjsip/sip_endpoint.c

    r4154 r4275  
    813813} 
    814814 
     815/* Init with default */ 
     816PJ_DEF(void) pjsip_process_rdata_param_default(pjsip_process_rdata_param *p) 
     817{ 
     818    pj_bzero(p, sizeof(*p)); 
     819} 
     820 
     821/* Distribute rdata */ 
     822PJ_DEF(pj_status_t) pjsip_endpt_process_rx_data( pjsip_endpoint *endpt, 
     823                                                 pjsip_rx_data *rdata, 
     824                                                 pjsip_process_rdata_param *p, 
     825                                                 pj_bool_t *p_handled) 
     826{ 
     827    pjsip_msg *msg; 
     828    pjsip_process_rdata_param def_prm; 
     829    pjsip_module *mod; 
     830    pj_bool_t handled = PJ_FALSE; 
     831    unsigned i; 
     832    pj_status_t status; 
     833 
     834    PJ_ASSERT_RETURN(endpt && rdata, PJ_EINVAL); 
     835 
     836    if (p==NULL) { 
     837        p = &def_prm; 
     838        pjsip_process_rdata_param_default(p); 
     839    } 
     840 
     841    msg = rdata->msg_info.msg; 
     842 
     843    if (p_handled) 
     844        *p_handled = PJ_FALSE; 
     845 
     846    if (!p->silent) { 
     847        PJ_LOG(5, (THIS_FILE, "Distributing rdata to modules: %s", 
     848                   pjsip_rx_data_get_info(rdata))); 
     849        pj_log_push_indent(); 
     850    } 
     851 
     852    LOCK_MODULE_ACCESS(endpt); 
     853 
     854    /* Find start module */ 
     855    if (p->start_mod) { 
     856        mod = pj_list_find_node(&endpt->module_list, p->start_mod); 
     857        if (!mod) { 
     858            status = PJ_ENOTFOUND; 
     859            goto on_return; 
     860        } 
     861    } else { 
     862        mod = endpt->module_list.next; 
     863    } 
     864 
     865    /* Start after the specified index */ 
     866    for (i=0; i < p->idx_after_start && mod != &endpt->module_list; ++i) { 
     867        mod = mod->next; 
     868    } 
     869 
     870    /* Start with the specified priority */ 
     871    while (mod != &endpt->module_list && mod->priority < p->start_prio) { 
     872        mod = mod->next; 
     873    } 
     874 
     875    if (mod == &endpt->module_list) { 
     876        status = PJ_ENOTFOUND; 
     877        goto on_return; 
     878    } 
     879 
     880    /* Distribute */ 
     881    if (msg->type == PJSIP_REQUEST_MSG) { 
     882        do { 
     883            if (mod->on_rx_request) 
     884                handled = (*mod->on_rx_request)(rdata); 
     885            if (handled) 
     886                break; 
     887            mod = mod->next; 
     888        } while (mod != &endpt->module_list); 
     889    } else { 
     890        do { 
     891            if (mod->on_rx_response) 
     892                handled = (*mod->on_rx_response)(rdata); 
     893            if (handled) 
     894                break; 
     895            mod = mod->next; 
     896        } while (mod != &endpt->module_list); 
     897    } 
     898 
     899    status = PJ_SUCCESS; 
     900 
     901on_return: 
     902    if (p_handled) 
     903        *p_handled = handled; 
     904 
     905    UNLOCK_MODULE_ACCESS(endpt); 
     906    if (!p->silent) { 
     907        pj_log_pop_indent(); 
     908    } 
     909    return status; 
     910} 
     911 
    815912/* 
    816913 * This is the callback that is called by the transport manager when it  
     
    821918                                      pjsip_rx_data *rdata ) 
    822919{ 
    823     pjsip_msg *msg = rdata->msg_info.msg; 
     920    pjsip_process_rdata_param proc_prm; 
     921    pj_bool_t handled = PJ_FALSE; 
    824922 
    825923    if (status != PJ_SUCCESS) { 
     
    9281026#endif 
    9291027 
    930  
    931     /* Distribute to modules, starting from modules with highest priority */ 
    932     LOCK_MODULE_ACCESS(endpt); 
    933  
    934     if (msg->type == PJSIP_REQUEST_MSG) { 
    935         pjsip_module *mod; 
    936         pj_bool_t handled = PJ_FALSE; 
    937  
    938         mod = endpt->module_list.next; 
    939         while (mod != &endpt->module_list) { 
    940             if (mod->on_rx_request) 
    941                 handled = (*mod->on_rx_request)(rdata); 
    942             if (handled) 
    943                 break; 
    944             mod = mod->next; 
    945         } 
    946  
    947         /* No module is able to handle the request. */ 
    948         if (!handled) { 
    949             PJ_TODO(ENDPT_RESPOND_UNHANDLED_REQUEST); 
    950             PJ_LOG(4,(THIS_FILE, "Message %s from %s:%d was dropped/unhandled by" 
    951                                  " any modules", 
    952                                  pjsip_rx_data_get_info(rdata), 
    953                                  rdata->pkt_info.src_name, 
    954                                  rdata->pkt_info.src_port)); 
    955         } 
    956  
    957     } else { 
    958         pjsip_module *mod; 
    959         pj_bool_t handled = PJ_FALSE; 
    960  
    961         mod = endpt->module_list.next; 
    962         while (mod != &endpt->module_list) { 
    963             if (mod->on_rx_response) 
    964                 handled = (*mod->on_rx_response)(rdata); 
    965             if (handled) 
    966                 break; 
    967             mod = mod->next; 
    968         } 
    969  
    970         if (!handled) { 
    971             PJ_LOG(4,(THIS_FILE, "Message %s from %s:%d was dropped/unhandled" 
    972                                  " by any modules", 
    973                                  pjsip_rx_data_get_info(rdata), 
    974                                  rdata->pkt_info.src_name, 
    975                                  rdata->pkt_info.src_port)); 
    976         } 
    977     } 
    978  
    979     UNLOCK_MODULE_ACCESS(endpt); 
     1028    pjsip_process_rdata_param_default(&proc_prm); 
     1029    proc_prm.silent = PJ_TRUE; 
     1030 
     1031    pjsip_endpt_process_rx_data(endpt, rdata, &proc_prm, &handled); 
     1032 
     1033    /* No module is able to handle the message */ 
     1034    if (!handled) { 
     1035        PJ_LOG(4,(THIS_FILE, "%s from %s:%d was dropped/unhandled by" 
     1036                             " any modules", 
     1037                             pjsip_rx_data_get_info(rdata), 
     1038                             rdata->pkt_info.src_name, 
     1039                             rdata->pkt_info.src_port)); 
     1040    } 
    9801041 
    9811042    /* Must clear mod_data before returning rdata to transport, since 
  • pjproject/trunk/pjsip/src/pjsip/sip_transport.c

    r4262 r4275  
    603603} 
    604604 
     605/* Clone pjsip_rx_data. */ 
     606PJ_DEF(pj_status_t) pjsip_rx_data_clone( const pjsip_rx_data *src, 
     607                                         unsigned flags, 
     608                                         pjsip_rx_data **p_rdata) 
     609{ 
     610    pj_pool_t *pool; 
     611    pjsip_rx_data *dst; 
     612    pjsip_hdr *hdr; 
     613 
     614    PJ_ASSERT_RETURN(src && flags==0 && p_rdata, PJ_EINVAL); 
     615 
     616    pool = pj_pool_create(src->tp_info.pool->factory, 
     617                          "rtd%p", 
     618                          PJSIP_POOL_RDATA_LEN, 
     619                          PJSIP_POOL_RDATA_INC, 
     620                          NULL); 
     621    if (!pool) 
     622        return PJ_ENOMEM; 
     623 
     624    dst = PJ_POOL_ZALLOC_T(pool, pjsip_rx_data); 
     625 
     626    /* Parts of tp_info */ 
     627    dst->tp_info.pool = pool; 
     628    dst->tp_info.transport = (pjsip_transport*)src->tp_info.transport; 
     629 
     630    /* pkt_info can be memcopied */ 
     631    pj_memcpy(&dst->pkt_info, &src->pkt_info, sizeof(src->pkt_info)); 
     632 
     633    /* msg_info needs deep clone */ 
     634    dst->msg_info.msg_buf = dst->pkt_info.packet; 
     635    dst->msg_info.len = src->msg_info.len; 
     636    dst->msg_info.msg = pjsip_msg_clone(pool, src->msg_info.msg); 
     637    pj_list_init(&dst->msg_info.parse_err); 
     638 
     639#define GET_MSG_HDR2(TYPE, type, var)   \ 
     640                        case PJSIP_H_##TYPE: \ 
     641                            dst->msg_info.var = (pjsip_##type##_hdr*)hdr; \ 
     642                            break 
     643#define GET_MSG_HDR(TYPE, var_type)     GET_MSG_HDR2(TYPE, var_type, var_type) 
     644 
     645    hdr = dst->msg_info.msg->hdr.next; 
     646    while (hdr != &dst->msg_info.msg->hdr) { 
     647        switch (hdr->type) { 
     648        GET_MSG_HDR(CALL_ID, cid); 
     649        GET_MSG_HDR(FROM, from); 
     650        GET_MSG_HDR(TO, to); 
     651        GET_MSG_HDR(VIA, via); 
     652        GET_MSG_HDR(CSEQ, cseq); 
     653        GET_MSG_HDR(MAX_FORWARDS, max_fwd); 
     654        GET_MSG_HDR(ROUTE, route); 
     655        GET_MSG_HDR2(RECORD_ROUTE, rr, record_route); 
     656        GET_MSG_HDR(CONTENT_TYPE, ctype); 
     657        GET_MSG_HDR(CONTENT_LENGTH, clen); 
     658        GET_MSG_HDR(REQUIRE, require); 
     659        GET_MSG_HDR(SUPPORTED, supported); 
     660        default: 
     661            break; 
     662        } 
     663        hdr = hdr->next; 
     664    } 
     665 
     666#undef GET_MSG_HDR 
     667#undef GET_MSG_HDR2 
     668 
     669    *p_rdata = dst; 
     670 
     671    /* Finally add transport ref */ 
     672    return pjsip_transport_add_ref(dst->tp_info.transport); 
     673} 
     674 
     675/* Free previously cloned pjsip_rx_data. */ 
     676PJ_DEF(pj_status_t) pjsip_rx_data_free_cloned(pjsip_rx_data *rdata) 
     677{ 
     678    PJ_ASSERT_RETURN(rdata, PJ_EINVAL); 
     679 
     680    pjsip_transport_dec_ref(rdata->tp_info.transport); 
     681    pj_pool_release(rdata->tp_info.pool); 
     682 
     683    return PJ_SUCCESS; 
     684} 
     685 
    605686/***************************************************************************** 
    606687 * 
Note: See TracChangeset for help on using the changeset viewer.