Ignore:
Timestamp:
Oct 26, 2009 11:21:37 AM (10 years ago)
Author:
bennylp
Message:

Implement ticket #982: Support for SIP Message Summary/Message? Waiting Indication (MWI, RFC 3842)

  • PJSIP-SIMPLE:
    • implement MWI
  • PJSUA-LIB:
    • added "mwi_enabled" flag in account config
    • added "on_mwi_info" callback
  • pjsua app:
    • added "--mwi" option to enable MWI on account
    • added simple callback to log the NOTIFY message
  • other:
    • added SIPp scenario files to simulate UAS side
  • build:
    • added MWI support on VS6, VS2005, MMP, and Makefile
File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_pres.c

    r2960 r2968  
    18541854} 
    18551855 
     1856/*************************************************************************** 
     1857 * MWI 
     1858 */ 
     1859/* Callback called when *client* subscription state has changed. */ 
     1860static void mwi_evsub_on_state( pjsip_evsub *sub, pjsip_event *event) 
     1861{ 
     1862    pjsua_acc *acc; 
     1863 
     1864    PJ_UNUSED_ARG(event); 
     1865 
     1866    /* Note: #937: no need to acuire PJSUA_LOCK here. Since the buddy has 
     1867     *   a dialog attached to it, lock_buddy() will use the dialog 
     1868     *   lock, which we are currently holding! 
     1869     */ 
     1870    acc = (pjsua_acc*) pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id); 
     1871    if (!acc) 
     1872        return; 
     1873 
     1874    PJ_LOG(4,(THIS_FILE,  
     1875              "MWI subscription for %.*s is %s", 
     1876              (int)acc->cfg.id.slen, acc->cfg.id.ptr,  
     1877              pjsip_evsub_get_state_name(sub))); 
     1878 
     1879    if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) { 
     1880        /* Clear subscription */ 
     1881        acc->mwi_dlg = NULL; 
     1882        acc->mwi_sub = NULL; 
     1883        pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, NULL); 
     1884 
     1885    } 
     1886} 
     1887 
     1888/* Callback called when we receive NOTIFY */ 
     1889static void mwi_evsub_on_rx_notify(pjsip_evsub *sub,  
     1890                                   pjsip_rx_data *rdata, 
     1891                                   int *p_st_code, 
     1892                                   pj_str_t **p_st_text, 
     1893                                   pjsip_hdr *res_hdr, 
     1894                                   pjsip_msg_body **p_body) 
     1895{ 
     1896    pjsua_mwi_info mwi_info; 
     1897    pjsua_acc *acc; 
     1898 
     1899    PJ_UNUSED_ARG(p_st_code); 
     1900    PJ_UNUSED_ARG(p_st_text); 
     1901    PJ_UNUSED_ARG(res_hdr); 
     1902    PJ_UNUSED_ARG(p_body); 
     1903 
     1904    acc = (pjsua_acc*) pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id); 
     1905    if (!acc) 
     1906        return; 
     1907 
     1908    /* Construct mwi_info */ 
     1909    pj_bzero(&mwi_info, sizeof(mwi_info)); 
     1910    mwi_info.evsub = sub; 
     1911    mwi_info.rdata = rdata; 
     1912 
     1913    /* Call callback */ 
     1914    if (pjsua_var.ua_cfg.cb.on_mwi_info) { 
     1915        (*pjsua_var.ua_cfg.cb.on_mwi_info)(acc->index, &mwi_info); 
     1916    } 
     1917} 
     1918 
     1919 
     1920/* Event subscription callback. */ 
     1921static pjsip_evsub_user mwi_cb =  
     1922{ 
     1923    &mwi_evsub_on_state,   
     1924    NULL,   /* on_tsx_state: not interested */ 
     1925    NULL,   /* on_rx_refresh: don't care about SUBSCRIBE refresh, unless  
     1926             * we want to authenticate  
     1927             */ 
     1928 
     1929    &mwi_evsub_on_rx_notify, 
     1930 
     1931    NULL,   /* on_client_refresh: Use default behaviour, which is to  
     1932             * refresh client subscription. */ 
     1933 
     1934    NULL,   /* on_server_timeout: Use default behaviour, which is to send  
     1935             * NOTIFY to terminate.  
     1936             */ 
     1937}; 
     1938 
     1939void pjsua_start_mwi(pjsua_acc *acc) 
     1940{ 
     1941    pj_pool_t *tmp_pool = NULL; 
     1942    pj_str_t contact; 
     1943    pjsip_tx_data *tdata; 
     1944    pj_status_t status; 
     1945 
     1946    if (!acc->cfg.mwi_enabled) { 
     1947        if (acc->mwi_sub) { 
     1948            /* Terminate MWI subscription */ 
     1949            pjsip_tx_data *tdata; 
     1950            pjsip_evsub *sub = acc->mwi_sub; 
     1951 
     1952            /* Detach sub from this account */ 
     1953            acc->mwi_sub = NULL; 
     1954            acc->mwi_dlg = NULL; 
     1955            pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, NULL); 
     1956 
     1957            /* Unsubscribe */ 
     1958            status = pjsip_mwi_initiate(acc->mwi_sub, 0, &tdata); 
     1959            if (status == PJ_SUCCESS) { 
     1960                status = pjsip_mwi_send_request(acc->mwi_sub, tdata); 
     1961            } 
     1962        } 
     1963        return; 
     1964    } 
     1965 
     1966    if (acc->mwi_sub) { 
     1967        /* Subscription is already active */ 
     1968        return; 
     1969 
     1970    } 
     1971 
     1972    /* Generate suitable Contact header unless one is already set in  
     1973     * the account 
     1974     */ 
     1975    if (acc->contact.slen) { 
     1976        contact = acc->contact; 
     1977    } else { 
     1978        tmp_pool = pjsua_pool_create("tmpmwi", 512, 256); 
     1979        status = pjsua_acc_create_uac_contact(tmp_pool, &contact, 
     1980                                              acc->index, &acc->cfg.id); 
     1981        if (status != PJ_SUCCESS) { 
     1982            pjsua_perror(THIS_FILE, "Unable to generate Contact header",  
     1983                         status); 
     1984            pj_pool_release(tmp_pool); 
     1985            return; 
     1986        } 
     1987    } 
     1988 
     1989    /* Create UAC dialog */ 
     1990    status = pjsip_dlg_create_uac( pjsip_ua_instance(), 
     1991                                   &acc->cfg.id, 
     1992                                   &contact, 
     1993                                   &acc->cfg.id, 
     1994                                   NULL, &acc->mwi_dlg); 
     1995    if (status != PJ_SUCCESS) { 
     1996        pjsua_perror(THIS_FILE, "Unable to create dialog", status); 
     1997        if (tmp_pool) pj_pool_release(tmp_pool); 
     1998        return; 
     1999    } 
     2000 
     2001    /* Increment the dialog's lock otherwise when presence session creation 
     2002     * fails the dialog will be destroyed prematurely. 
     2003     */ 
     2004    pjsip_dlg_inc_lock(acc->mwi_dlg); 
     2005 
     2006    /* Create UAC subscription */ 
     2007    status = pjsip_mwi_create_uac(acc->mwi_dlg, &mwi_cb,  
     2008                                  PJSIP_EVSUB_NO_EVENT_ID, &acc->mwi_sub); 
     2009    if (status != PJ_SUCCESS) { 
     2010        pjsua_perror(THIS_FILE, "Error creating MWI subscription", status); 
     2011        if (tmp_pool) pj_pool_release(tmp_pool); 
     2012        pjsip_dlg_dec_lock(acc->mwi_dlg); 
     2013        return; 
     2014    } 
     2015 
     2016    /* If account is locked to specific transport, then lock dialog 
     2017     * to this transport too. 
     2018     */ 
     2019    if (acc->cfg.transport_id != PJSUA_INVALID_ID) { 
     2020        pjsip_tpselector tp_sel; 
     2021 
     2022        pjsua_init_tpselector(acc->cfg.transport_id, &tp_sel); 
     2023        pjsip_dlg_set_transport(acc->mwi_dlg, &tp_sel); 
     2024    } 
     2025 
     2026    /* Set route-set */ 
     2027    if (!pj_list_empty(&acc->route_set)) { 
     2028        pjsip_dlg_set_route_set(acc->mwi_dlg, &acc->route_set); 
     2029    } 
     2030 
     2031    /* Set credentials */ 
     2032    if (acc->cred_cnt) { 
     2033        pjsip_auth_clt_set_credentials( &acc->mwi_dlg->auth_sess,  
     2034                                        acc->cred_cnt, acc->cred); 
     2035    } 
     2036 
     2037    /* Set authentication preference */ 
     2038    pjsip_auth_clt_set_prefs(&acc->mwi_dlg->auth_sess, &acc->cfg.auth_pref); 
     2039 
     2040    pjsip_evsub_set_mod_data(acc->mwi_sub, pjsua_var.mod.id, acc); 
     2041 
     2042    status = pjsip_mwi_initiate(acc->mwi_sub, -1, &tdata); 
     2043    if (status != PJ_SUCCESS) { 
     2044        pjsip_dlg_dec_lock(acc->mwi_dlg); 
     2045        if (acc->mwi_sub) { 
     2046            pjsip_pres_terminate(acc->mwi_sub, PJ_FALSE); 
     2047        } 
     2048        acc->mwi_sub = NULL; 
     2049        acc->mwi_dlg = NULL; 
     2050        pjsua_perror(THIS_FILE, "Unable to create initial MWI SUBSCRIBE",  
     2051                     status); 
     2052        if (tmp_pool) pj_pool_release(tmp_pool); 
     2053        return; 
     2054    } 
     2055 
     2056    pjsua_process_msg_data(tdata, NULL); 
     2057 
     2058    status = pjsip_pres_send_request(acc->mwi_sub, tdata); 
     2059    if (status != PJ_SUCCESS) { 
     2060        pjsip_dlg_dec_lock(acc->mwi_dlg); 
     2061        if (acc->mwi_sub) { 
     2062            pjsip_pres_terminate(acc->mwi_sub, PJ_FALSE); 
     2063        } 
     2064        acc->mwi_sub = NULL; 
     2065        acc->mwi_dlg = NULL; 
     2066        pjsua_perror(THIS_FILE, "Unable to send initial MWI SUBSCRIBE",  
     2067                     status); 
     2068        if (tmp_pool) pj_pool_release(tmp_pool); 
     2069        return; 
     2070    } 
     2071 
     2072    pjsip_dlg_dec_lock(acc->mwi_dlg); 
     2073    if (tmp_pool) pj_pool_release(tmp_pool); 
     2074 
     2075} 
     2076 
     2077 
     2078/***************************************************************************/ 
     2079 
    18562080/* Timer callback to re-create client subscription */ 
    18572081static void pres_timer_cb(pj_timer_heap_t *th, 
     
    18612085    pj_time_val delay = { PJSUA_PRES_TIMER, 0 }; 
    18622086 
    1863     /* Retry failed PUBLISH requests */ 
     2087    entry->id = PJ_FALSE; 
     2088 
     2089    /* Retry failed PUBLISH and MWI SUBSCRIBE requests */ 
    18642090    for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.acc); ++i) { 
    18652091        pjsua_acc *acc = &pjsua_var.acc[i]; 
     2092 
     2093        /* Retry PUBLISH */ 
    18662094        if (acc->cfg.publish_enabled && acc->publish_sess==NULL) 
    18672095            pjsua_pres_init_publish_acc(acc->index); 
    1868     } 
    1869  
    1870     entry->id = PJ_FALSE; 
     2096 
     2097        /* Re-subscribe MWI subscription if it's terminated prematurely */ 
     2098        if (acc->cfg.mwi_enabled && !acc->mwi_sub) 
     2099            pjsua_start_mwi(acc); 
     2100    } 
    18712101 
    18722102    /* #937: No need to do bulk client refresh, as buddies have their 
Note: See TracChangeset for help on using the changeset viewer.