Ignore:
Timestamp:
Jun 13, 2006 10:57:13 PM (18 years ago)
Author:
bennylp
Message:

-- REWRITE OF PJSUA API --

File:
1 edited

Legend:

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

    r492 r503  
    1818 */ 
    1919#include <pjsua-lib/pjsua.h> 
    20 #include "pjsua_imp.h" 
    21  
    22 /* 
    23  * pjsua_pres.c 
    24  * 
    25  * Presence related stuffs. 
    26  */ 
     20#include <pjsua-lib/pjsua_internal.h> 
     21 
    2722 
    2823#define THIS_FILE   "pjsua_pres.c" 
    2924 
    3025 
    31  
    32 /* ************************************************************************** 
    33  * THE FOLLOWING PART HANDLES SERVER SUBSCRIPTION 
    34  * ************************************************************************** 
     26/* 
     27 * Get total number of buddies. 
     28 */ 
     29PJ_DEF(unsigned) pjsua_get_buddy_count(void) 
     30{ 
     31    return pjsua_var.buddy_cnt; 
     32} 
     33 
     34 
     35/* 
     36 * Check if buddy ID is valid. 
     37 */ 
     38PJ_DEF(pj_bool_t) pjsua_buddy_is_valid(pjsua_buddy_id buddy_id) 
     39{ 
     40    return buddy_id>=0 && buddy_id<PJ_ARRAY_SIZE(pjsua_var.buddy) && 
     41           pjsua_var.buddy[buddy_id].uri.slen != 0; 
     42} 
     43 
     44 
     45/* 
     46 * Enum buddy IDs. 
     47 */ 
     48PJ_DEF(pj_status_t) pjsua_enum_buddies( pjsua_buddy_id ids[], 
     49                                        unsigned *count) 
     50{ 
     51    unsigned i, c; 
     52 
     53    PJ_ASSERT_RETURN(ids && count, PJ_EINVAL); 
     54 
     55    PJSUA_LOCK(); 
     56 
     57    for (i=0, c=0; c<*count && i<PJ_ARRAY_SIZE(pjsua_var.buddy); ++i) { 
     58        if (!pjsua_var.buddy[i].uri.slen) 
     59            continue; 
     60        ids[c] = i; 
     61        ++c; 
     62    } 
     63 
     64    *count = c; 
     65 
     66    PJSUA_UNLOCK(); 
     67 
     68    return PJ_SUCCESS; 
     69 
     70} 
     71 
     72 
     73/* 
     74 * Get detailed buddy info. 
     75 */ 
     76PJ_DEF(pj_status_t) pjsua_buddy_get_info( pjsua_buddy_id buddy_id, 
     77                                          pjsua_buddy_info *info) 
     78{ 
     79    int total=0; 
     80    pjsua_buddy *buddy; 
     81 
     82    PJ_ASSERT_RETURN(buddy_id>=0 &&  
     83                       buddy_id<(int)PJ_ARRAY_SIZE(pjsua_var.buddy),  
     84                     PJ_EINVAL); 
     85 
     86    PJSUA_LOCK(); 
     87 
     88    pj_memset(info, 0, sizeof(pjsua_buddy_info)); 
     89 
     90    buddy = &pjsua_var.buddy[buddy_id]; 
     91    info->id = buddy->index; 
     92    if (pjsua_var.buddy[buddy_id].uri.slen == 0) { 
     93        PJSUA_UNLOCK(); 
     94        return PJ_SUCCESS; 
     95    } 
     96 
     97    /* uri */ 
     98    info->uri.ptr = info->buf_ + total; 
     99    pj_strncpy(&info->uri, &buddy->uri, sizeof(info->buf_)-total); 
     100    total += info->uri.slen; 
     101 
     102    /* contact */ 
     103    info->contact.ptr = info->buf_ + total; 
     104    pj_strncpy(&info->contact, &buddy->contact, sizeof(info->buf_)-total); 
     105    total += info->contact.slen; 
     106         
     107    /* status and status text */     
     108    if (buddy->sub == NULL || buddy->status.info_cnt==0) { 
     109        info->status = PJSUA_BUDDY_STATUS_UNKNOWN; 
     110        info->status_text = pj_str("?"); 
     111    } else if (pjsua_var.buddy[buddy_id].status.info[0].basic_open) { 
     112        info->status = PJSUA_BUDDY_STATUS_ONLINE; 
     113        info->status_text = pj_str("Online"); 
     114    } else { 
     115        info->status = PJSUA_BUDDY_STATUS_OFFLINE; 
     116        info->status_text = pj_str("Offline"); 
     117    } 
     118 
     119    /* monitor pres */ 
     120    info->monitor_pres = buddy->monitor; 
     121 
     122    PJSUA_UNLOCK(); 
     123    return PJ_SUCCESS; 
     124} 
     125 
     126 
     127/* 
     128 * Reset buddy descriptor. 
     129 */ 
     130static void reset_buddy(pjsua_buddy_id id) 
     131{ 
     132    pj_memset(&pjsua_var.buddy[id], 0, sizeof(pjsua_var.buddy[id])); 
     133    pjsua_var.buddy[id].index = id; 
     134} 
     135 
     136 
     137/* 
     138 * Add new buddy. 
     139 */ 
     140PJ_DEF(pj_status_t) pjsua_buddy_add( const pjsua_buddy_config *cfg, 
     141                                     pjsua_buddy_id *p_buddy_id) 
     142{ 
     143    pjsip_name_addr *url; 
     144    pjsip_sip_uri *sip_uri; 
     145    int index; 
     146    pj_str_t tmp; 
     147 
     148    PJ_ASSERT_RETURN(pjsua_var.buddy_cnt <=  
     149                        PJ_ARRAY_SIZE(pjsua_var.buddy), 
     150                     PJ_ETOOMANY); 
     151 
     152    PJSUA_LOCK(); 
     153 
     154    /* Find empty slot */ 
     155    for (index=0; index<PJ_ARRAY_SIZE(pjsua_var.buddy); ++index) { 
     156        if (pjsua_var.buddy[index].uri.slen == 0) 
     157            break; 
     158    } 
     159 
     160    /* Expect to find an empty slot */ 
     161    if (index == PJ_ARRAY_SIZE(pjsua_var.buddy)) { 
     162        PJSUA_UNLOCK(); 
     163        /* This shouldn't happen */ 
     164        pj_assert(!"index < PJ_ARRAY_SIZE(pjsua_var.buddy)"); 
     165        return PJ_ETOOMANY; 
     166    } 
     167 
     168 
     169    /* Get name and display name for buddy */ 
     170    pj_strdup_with_null(pjsua_var.pool, &tmp, &cfg->uri); 
     171    url = (pjsip_name_addr*)pjsip_parse_uri(pjsua_var.pool, tmp.ptr, tmp.slen, 
     172                                            PJSIP_PARSE_URI_AS_NAMEADDR); 
     173 
     174    if (url == NULL) { 
     175        pjsua_perror(THIS_FILE, "Unable to add buddy", PJSIP_EINVALIDURI); 
     176        PJSUA_UNLOCK(); 
     177        return PJSIP_EINVALIDURI; 
     178    } 
     179 
     180    /* Reset buddy, to make sure everything is cleared with default 
     181     * values 
     182     */ 
     183    reset_buddy(index); 
     184 
     185    /* Save URI */ 
     186    pjsua_var.buddy[index].uri = tmp; 
     187 
     188    sip_uri = (pjsip_sip_uri*) url->uri; 
     189    pjsua_var.buddy[index].name = sip_uri->user; 
     190    pjsua_var.buddy[index].display = url->display; 
     191    pjsua_var.buddy[index].host = sip_uri->host; 
     192    pjsua_var.buddy[index].port = sip_uri->port; 
     193    pjsua_var.buddy[index].monitor = cfg->subscribe; 
     194    if (pjsua_var.buddy[index].port == 0) 
     195        pjsua_var.buddy[index].port = 5060; 
     196 
     197    if (p_buddy_id) 
     198        *p_buddy_id = index; 
     199 
     200    pjsua_var.buddy_cnt++; 
     201 
     202    pjsua_buddy_subscribe_pres(index, cfg->subscribe); 
     203 
     204    PJSUA_UNLOCK(); 
     205 
     206    return PJ_SUCCESS; 
     207} 
     208 
     209 
     210/* 
     211 * Delete buddy. 
     212 */ 
     213PJ_DEF(pj_status_t) pjsua_buddy_del(pjsua_buddy_id buddy_id) 
     214{ 
     215    PJ_ASSERT_RETURN(buddy_id>=0 &&  
     216                        buddy_id<(int)PJ_ARRAY_SIZE(pjsua_var.buddy), 
     217                     PJ_EINVAL); 
     218 
     219    PJSUA_LOCK(); 
     220 
     221    if (pjsua_var.buddy[buddy_id].uri.slen == 0) { 
     222        PJSUA_UNLOCK(); 
     223        return PJ_SUCCESS; 
     224    } 
     225 
     226    /* Unsubscribe presence */ 
     227    pjsua_buddy_subscribe_pres(buddy_id, PJ_FALSE); 
     228 
     229    /* Remove buddy */ 
     230    pjsua_var.buddy[buddy_id].uri.slen = 0; 
     231    pjsua_var.buddy_cnt--; 
     232 
     233    /* Reset buddy struct */ 
     234    reset_buddy(buddy_id); 
     235 
     236    PJSUA_UNLOCK(); 
     237    return PJ_SUCCESS; 
     238} 
     239 
     240 
     241/* 
     242 * Enable/disable buddy's presence monitoring. 
     243 */ 
     244PJ_DEF(pj_status_t) pjsua_buddy_subscribe_pres( pjsua_buddy_id buddy_id, 
     245                                                pj_bool_t subscribe) 
     246{ 
     247    pjsua_buddy *buddy; 
     248 
     249    PJ_ASSERT_RETURN(buddy_id>=0 &&  
     250                        buddy_id<(int)PJ_ARRAY_SIZE(pjsua_var.buddy), 
     251                     PJ_EINVAL); 
     252 
     253    PJSUA_LOCK(); 
     254 
     255    buddy = &pjsua_var.buddy[buddy_id]; 
     256    buddy->monitor = subscribe; 
     257    pjsua_pres_refresh(); 
     258 
     259    PJSUA_UNLOCK(); 
     260 
     261    return PJ_SUCCESS; 
     262} 
     263 
     264 
     265/* 
     266 * Dump presence subscriptions to log file. 
     267 */ 
     268PJ_DEF(void) pjsua_pres_dump(pj_bool_t verbose) 
     269{ 
     270    unsigned acc_id; 
     271    unsigned i; 
     272 
     273     
     274    PJSUA_LOCK(); 
     275 
     276    /* 
     277     * When no detail is required, just dump number of server and client 
     278     * subscriptions. 
     279     */ 
     280    if (verbose == PJ_FALSE) { 
     281         
     282        int count = 0; 
     283 
     284        for (acc_id=0; acc_id<PJ_ARRAY_SIZE(pjsua_var.acc); ++acc_id) { 
     285 
     286            if (!pjsua_var.acc[acc_id].valid) 
     287                continue; 
     288 
     289            if (!pj_list_empty(&pjsua_var.acc[acc_id].pres_srv_list)) { 
     290                struct pjsua_srv_pres *uapres; 
     291 
     292                uapres = pjsua_var.acc[acc_id].pres_srv_list.next; 
     293                while (uapres != &pjsua_var.acc[acc_id].pres_srv_list) { 
     294                    ++count; 
     295                    uapres = uapres->next; 
     296                } 
     297            } 
     298        } 
     299 
     300        PJ_LOG(3,(THIS_FILE, "Number of server/UAS subscriptions: %d",  
     301                  count)); 
     302 
     303        count = 0; 
     304 
     305        for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.buddy); ++i) { 
     306            if (pjsua_var.buddy[i].uri.slen == 0) 
     307                continue; 
     308            if (pjsua_var.buddy[i].sub) { 
     309                ++count; 
     310            } 
     311        } 
     312 
     313        PJ_LOG(3,(THIS_FILE, "Number of client/UAC subscriptions: %d",  
     314                  count)); 
     315        PJSUA_UNLOCK(); 
     316        return; 
     317    } 
     318     
     319 
     320    /* 
     321     * Dumping all server (UAS) subscriptions 
     322     */ 
     323    PJ_LOG(3,(THIS_FILE, "Dumping pjsua server subscriptions:")); 
     324 
     325    for (acc_id=0; acc_id<(int)PJ_ARRAY_SIZE(pjsua_var.acc); ++acc_id) { 
     326 
     327        if (!pjsua_var.acc[acc_id].valid) 
     328            continue; 
     329 
     330        PJ_LOG(3,(THIS_FILE, "  %.*s", 
     331                  (int)pjsua_var.acc[acc_id].cfg.id.slen, 
     332                  pjsua_var.acc[acc_id].cfg.id.ptr)); 
     333 
     334        if (pj_list_empty(&pjsua_var.acc[acc_id].pres_srv_list)) { 
     335 
     336            PJ_LOG(3,(THIS_FILE, "  - none - ")); 
     337 
     338        } else { 
     339            struct pjsua_srv_pres *uapres; 
     340 
     341            uapres = pjsua_var.acc[acc_id].pres_srv_list.next; 
     342            while (uapres != &pjsua_var.acc[acc_id].pres_srv_list) { 
     343             
     344                PJ_LOG(3,(THIS_FILE, "    %10s %s", 
     345                          pjsip_evsub_get_state_name(uapres->sub), 
     346                          uapres->remote)); 
     347 
     348                uapres = uapres->next; 
     349            } 
     350        } 
     351    } 
     352 
     353    /* 
     354     * Dumping all client (UAC) subscriptions 
     355     */ 
     356    PJ_LOG(3,(THIS_FILE, "Dumping pjsua client subscriptions:")); 
     357 
     358    if (pjsua_var.buddy_cnt == 0) { 
     359 
     360        PJ_LOG(3,(THIS_FILE, "  - no buddy list - ")); 
     361 
     362    } else { 
     363        for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.buddy); ++i) { 
     364 
     365            if (pjsua_var.buddy[i].uri.slen == 0) 
     366                continue; 
     367 
     368            if (pjsua_var.buddy[i].sub) { 
     369                PJ_LOG(3,(THIS_FILE, "  %10s %.*s", 
     370                          pjsip_evsub_get_state_name(pjsua_var.buddy[i].sub), 
     371                          (int)pjsua_var.buddy[i].uri.slen, 
     372                          pjsua_var.buddy[i].uri.ptr)); 
     373            } else { 
     374                PJ_LOG(3,(THIS_FILE, "  %10s %.*s", 
     375                          "(null)", 
     376                          (int)pjsua_var.buddy[i].uri.slen, 
     377                          pjsua_var.buddy[i].uri.ptr)); 
     378            } 
     379        } 
     380    } 
     381 
     382    PJSUA_UNLOCK(); 
     383} 
     384 
     385 
     386/*************************************************************************** 
     387 * Server subscription. 
    35388 */ 
    36389 
     
    61414static void pres_evsub_on_srv_state( pjsip_evsub *sub, pjsip_event *event) 
    62415{ 
    63     pjsua_srv_pres *uapres = pjsip_evsub_get_mod_data(sub, pjsua.mod.id); 
     416    pjsua_srv_pres *uapres; 
    64417 
    65418    PJ_UNUSED_ARG(event); 
    66419 
     420    PJSUA_LOCK(); 
     421 
     422    uapres = pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id); 
    67423    if (uapres) { 
    68424        PJ_LOG(3,(THIS_FILE, "Server subscription to %s is %s", 
     
    70426 
    71427        if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) { 
    72             pjsip_evsub_set_mod_data(sub, pjsua.mod.id, NULL); 
     428            pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, NULL); 
    73429            pj_list_erase(uapres); 
    74430        } 
    75431    } 
     432 
     433    PJSUA_UNLOCK(); 
    76434} 
    77435 
     
    81439static pj_bool_t pres_on_rx_request(pjsip_rx_data *rdata) 
    82440{ 
    83     int acc_index; 
     441    int acc_id; 
    84442    pjsua_acc_config *acc_config; 
    85443    pjsip_method *req_method = &rdata->msg_info.msg->line.req.method; 
     
    97455    /* Incoming SUBSCRIBE: */ 
    98456 
     457    PJSUA_LOCK(); 
     458 
    99459    /* Find which account for the incoming request. */ 
    100     acc_index = pjsua_acc_find_for_incoming(rdata); 
    101     acc_config = &pjsua.config.acc_config[acc_index]; 
     460    acc_id = pjsua_acc_find_for_incoming(rdata); 
     461    acc_config = &pjsua_var.acc[acc_id].cfg; 
    102462 
    103463    /* Create UAS dialog: */ 
     
    109469                     "Unable to create UAS dialog for subscription",  
    110470                     status); 
    111         return PJ_FALSE; 
     471        PJSUA_UNLOCK(); 
     472        return PJ_TRUE; 
    112473    } 
    113474 
     
    122483        pjsua_perror(THIS_FILE, "Unable to create server subscription",  
    123484                     status); 
    124         return PJ_FALSE; 
     485        PJSUA_UNLOCK(); 
     486        return PJ_TRUE; 
    125487    } 
    126488 
     
    136498        uapres->remote[status] = '\0'; 
    137499 
    138     pjsip_evsub_set_mod_data(sub, pjsua.mod.id, uapres); 
     500    pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, uapres); 
    139501 
    140502    /* Add server subscription to the list: */ 
    141     pj_list_push_back(&pjsua.acc[acc_index].pres_srv_list, uapres); 
     503    pj_list_push_back(&pjsua_var.acc[acc_id].pres_srv_list, uapres); 
    142504 
    143505 
     
    149511        pj_list_erase(uapres); 
    150512        pjsip_pres_terminate(sub, PJ_FALSE); 
     513        PJSUA_UNLOCK(); 
    151514        return PJ_FALSE; 
    152515    } 
     
    156519    pj_memset(&pres_status, 0, sizeof(pres_status)); 
    157520    pres_status.info_cnt = 1; 
    158     pres_status.info[0].basic_open = pjsua.acc[acc_index].online_status; 
    159     //Both pjsua.local_uri and pjsua.contact_uri are enclosed in "<" and ">" 
     521    pres_status.info[0].basic_open = pjsua_var.acc[acc_id].online_status; 
     522    //Both pjsua_var.local_uri and pjsua_var.contact_uri are enclosed in "<" and ">" 
    160523    //causing XML parsing to fail. 
    161     //pres_status.info[0].contact = pjsua.local_uri; 
     524    //pres_status.info[0].contact = pjsua_var.local_uri; 
    162525 
    163526    pjsip_pres_set_status(sub, &pres_status); 
     
    174537        pj_list_erase(uapres); 
    175538        pjsip_pres_terminate(sub, PJ_FALSE); 
     539        PJSUA_UNLOCK(); 
    176540        return PJ_FALSE; 
    177541    } 
     
    180544    /* Done: */ 
    181545 
     546    PJSUA_UNLOCK(); 
     547 
    182548    return PJ_TRUE; 
    183549} 
    184550 
    185551 
     552/* Terminate server subscription for the account */ 
     553void pjsua_pres_delete_acc(int acc_id) 
     554{ 
     555    pjsua_srv_pres *uapres; 
     556 
     557    uapres = pjsua_var.acc[acc_id].pres_srv_list.next; 
     558 
     559    while (uapres != &pjsua_var.acc[acc_id].pres_srv_list) { 
     560         
     561        pjsip_pres_status pres_status; 
     562        pj_str_t reason = { "noresource", 10 }; 
     563        pjsip_tx_data *tdata; 
     564 
     565        pjsip_pres_get_status(uapres->sub, &pres_status); 
     566         
     567        pres_status.info[0].basic_open = pjsua_var.acc[acc_id].online_status; 
     568        pjsip_pres_set_status(uapres->sub, &pres_status); 
     569 
     570        if (pjsip_pres_notify(uapres->sub,  
     571                              PJSIP_EVSUB_STATE_TERMINATED, NULL, 
     572                              &reason, &tdata)==PJ_SUCCESS) 
     573        { 
     574            pjsip_pres_send_request(uapres->sub, tdata); 
     575        } 
     576 
     577        uapres = uapres->next; 
     578    } 
     579} 
     580 
     581 
    186582/* Refresh subscription (e.g. when our online status has changed) */ 
    187 static void refresh_server_subscription(int acc_index) 
     583static void refresh_server_subscription(int acc_id) 
    188584{ 
    189585    pjsua_srv_pres *uapres; 
    190586 
    191     uapres = pjsua.acc[acc_index].pres_srv_list.next; 
    192  
    193     while (uapres != &pjsua.acc[acc_index].pres_srv_list) { 
     587    uapres = pjsua_var.acc[acc_id].pres_srv_list.next; 
     588 
     589    while (uapres != &pjsua_var.acc[acc_id].pres_srv_list) { 
    194590         
    195591        pjsip_pres_status pres_status; 
     
    197593 
    198594        pjsip_pres_get_status(uapres->sub, &pres_status); 
    199         if (pres_status.info[0].basic_open != pjsua.acc[acc_index].online_status) { 
    200             pres_status.info[0].basic_open = pjsua.acc[acc_index].online_status; 
     595        if (pres_status.info[0].basic_open != pjsua_var.acc[acc_id].online_status) { 
     596            pres_status.info[0].basic_open = pjsua_var.acc[acc_id].online_status; 
    201597            pjsip_pres_set_status(uapres->sub, &pres_status); 
    202598 
    203             if (pjsua.quit_flag) { 
    204                 pj_str_t reason = { "noresource", 10 }; 
    205                 if (pjsip_pres_notify(uapres->sub,  
    206                                       PJSIP_EVSUB_STATE_TERMINATED, NULL, 
    207                                       &reason, &tdata)==PJ_SUCCESS) 
    208                 { 
    209                     pjsip_pres_send_request(uapres->sub, tdata); 
    210                 } 
    211             } else { 
    212                 if (pjsip_pres_current_notify(uapres->sub, &tdata)==PJ_SUCCESS) 
    213                     pjsip_pres_send_request(uapres->sub, tdata); 
    214             } 
     599            if (pjsip_pres_current_notify(uapres->sub, &tdata)==PJ_SUCCESS) 
     600                pjsip_pres_send_request(uapres->sub, tdata); 
    215601        } 
    216602 
     
    221607 
    222608 
    223 /* ************************************************************************** 
    224  * THE FOLLOWING PART HANDLES CLIENT SUBSCRIPTION 
    225  * ************************************************************************** 
     609/*************************************************************************** 
     610 * Client subscription. 
    226611 */ 
    227612 
     
    233618    PJ_UNUSED_ARG(event); 
    234619 
    235     buddy = pjsip_evsub_get_mod_data(sub, pjsua.mod.id); 
     620    PJSUA_LOCK(); 
     621 
     622    buddy = pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id); 
    236623    if (buddy) { 
    237624        PJ_LOG(3,(THIS_FILE,  
    238625                  "Presence subscription to %.*s is %s", 
    239                   (int)pjsua.config.buddy_uri[buddy->index].slen, 
    240                   pjsua.config.buddy_uri[buddy->index].ptr,  
     626                  (int)pjsua_var.buddy[buddy->index].uri.slen, 
     627                  pjsua_var.buddy[buddy->index].uri.ptr,  
    241628                  pjsip_evsub_get_state_name(sub))); 
    242629 
     
    244631            buddy->sub = NULL; 
    245632            buddy->status.info_cnt = 0; 
    246             pjsip_evsub_set_mod_data(sub, pjsua.mod.id, NULL); 
     633            pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, NULL); 
    247634        } 
    248635 
    249636        /* Call callback */ 
    250         if (pjsua.cb.on_buddy_state) 
    251             (*pjsua.cb.on_buddy_state)(buddy->index); 
    252     } 
    253 } 
     637        if (pjsua_var.ua_cfg.cb.on_buddy_state) 
     638            (*pjsua_var.ua_cfg.cb.on_buddy_state)(buddy->index); 
     639    } 
     640 
     641    PJSUA_UNLOCK(); 
     642} 
     643 
     644 
     645/* Callback when transaction state has changed. */ 
     646static void pjsua_evsub_on_tsx_state(pjsip_evsub *sub,  
     647                                     pjsip_transaction *tsx, 
     648                                     pjsip_event *event) 
     649{ 
     650    pjsua_buddy *buddy; 
     651    pjsip_contact_hdr *contact_hdr; 
     652 
     653    PJSUA_LOCK(); 
     654 
     655    buddy = pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id); 
     656    if (!buddy) { 
     657        PJSUA_UNLOCK(); 
     658        return; 
     659    } 
     660 
     661    /* We only use this to update buddy's Contact, when it's not 
     662     * set. 
     663     */ 
     664    if (buddy->contact.slen != 0) { 
     665        /* Contact already set */ 
     666        PJSUA_UNLOCK(); 
     667        return; 
     668    } 
     669     
     670    /* Only care about 2xx response to outgoing SUBSCRIBE */ 
     671    if (tsx->status_code/100 != 2 || 
     672        tsx->role != PJSIP_UAC_ROLE || 
     673        event->type != PJSIP_EVENT_RX_MSG ||  
     674        pjsip_method_cmp(&tsx->method, &pjsip_subscribe_method)!=0) 
     675    { 
     676        PJSUA_UNLOCK(); 
     677        return; 
     678    } 
     679 
     680    /* Find contact header. */ 
     681    contact_hdr = pjsip_msg_find_hdr(event->body.rx_msg.rdata->msg_info.msg, 
     682                                     PJSIP_H_CONTACT, NULL); 
     683    if (!contact_hdr) { 
     684        PJSUA_UNLOCK(); 
     685        return; 
     686    } 
     687 
     688    buddy->contact.ptr = pj_pool_alloc(pjsua_var.pool, PJSIP_MAX_URL_SIZE); 
     689    buddy->contact.slen = pjsip_uri_print( PJSIP_URI_IN_CONTACT_HDR, 
     690                                           contact_hdr->uri, 
     691                                           buddy->contact.ptr,  
     692                                           PJSIP_MAX_URL_SIZE); 
     693    if (buddy->contact.slen < 0) 
     694        buddy->contact.slen = 0; 
     695 
     696    PJSUA_UNLOCK(); 
     697} 
     698 
    254699 
    255700/* Callback called when we receive NOTIFY */ 
     
    263708    pjsua_buddy *buddy; 
    264709 
    265     buddy = pjsip_evsub_get_mod_data(sub, pjsua.mod.id); 
     710    PJSUA_LOCK(); 
     711 
     712    buddy = pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id); 
    266713    if (buddy) { 
    267714        /* Update our info. */ 
     
    277724    PJ_UNUSED_ARG(res_hdr); 
    278725    PJ_UNUSED_ARG(p_body); 
     726 
     727    PJSUA_UNLOCK(); 
    279728} 
    280729 
     
    284733{ 
    285734    &pjsua_evsub_on_state,   
    286  
    287     NULL,   /* on_tsx_state: don't care about transaction state. */ 
     735    &pjsua_evsub_on_tsx_state, 
    288736 
    289737    NULL,   /* on_rx_refresh: don't care about SUBSCRIBE refresh, unless  
     
    305753static void subscribe_buddy_presence(unsigned index) 
    306754{ 
    307     int acc_index; 
    308     pjsua_acc_config *acc_config; 
     755    pjsua_buddy *buddy; 
     756    int acc_id; 
     757    pjsua_acc *acc; 
    309758    pjsip_dialog *dlg; 
    310759    pjsip_tx_data *tdata; 
    311760    pj_status_t status; 
    312761 
    313     acc_index = pjsua_acc_find_for_outgoing(&pjsua.config.buddy_uri[index]); 
    314  
    315     acc_config = &pjsua.config.acc_config[acc_index]; 
    316  
     762    buddy = &pjsua_var.buddy[index]; 
     763    acc_id = pjsua_acc_find_for_outgoing(&buddy->uri); 
     764 
     765    acc = &pjsua_var.acc[acc_id]; 
     766 
     767    /* Create UAC dialog */ 
    317768    status = pjsip_dlg_create_uac( pjsip_ua_instance(),  
    318                                    &acc_config->id, 
    319                                    &acc_config->contact, 
    320                                    &pjsua.config.buddy_uri[index], 
     769                                   &acc->cfg.id, 
     770                                   &acc->cfg.contact, 
     771                                   &buddy->uri, 
    321772                                   NULL, &dlg); 
    322773    if (status != PJ_SUCCESS) { 
     
    326777    } 
    327778 
    328     if (acc_config->cred_count) { 
     779    /* Set route-set */ 
     780    if (!pj_list_empty(&acc->route_set)) { 
     781        pjsip_dlg_set_route_set(dlg, &acc->route_set); 
     782    } 
     783 
     784    /* Set credentials */ 
     785    if (acc->cred_cnt) { 
    329786        pjsip_auth_clt_set_credentials( &dlg->auth_sess,  
    330                                         acc_config->cred_count, 
    331                                         acc_config->cred_info); 
     787                                        acc->cred_cnt, acc->cred); 
    332788    } 
    333789 
    334790    status = pjsip_pres_create_uac( dlg, &pres_callback,  
    335                                     &pjsua.buddies[index].sub); 
     791                                    &buddy->sub); 
    336792    if (status != PJ_SUCCESS) { 
    337         pjsua.buddies[index].sub = NULL; 
     793        pjsua_var.buddy[index].sub = NULL; 
    338794        pjsua_perror(THIS_FILE, "Unable to create presence client",  
    339795                     status); 
     
    342798    } 
    343799 
    344     pjsip_evsub_set_mod_data(pjsua.buddies[index].sub, pjsua.mod.id, 
    345                              &pjsua.buddies[index]); 
    346  
    347     status = pjsip_pres_initiate(pjsua.buddies[index].sub, -1, &tdata); 
     800    pjsip_evsub_set_mod_data(buddy->sub, pjsua_var.mod.id, buddy); 
     801 
     802    status = pjsip_pres_initiate(buddy->sub, -1, &tdata); 
    348803    if (status != PJ_SUCCESS) { 
    349         pjsip_pres_terminate(pjsua.buddies[index].sub, PJ_FALSE); 
    350         pjsua.buddies[index].sub = NULL; 
     804        pjsip_pres_terminate(buddy->sub, PJ_FALSE); 
     805        buddy->sub = NULL; 
    351806        pjsua_perror(THIS_FILE, "Unable to create initial SUBSCRIBE",  
    352807                     status); 
     
    354809    } 
    355810 
    356     status = pjsip_pres_send_request(pjsua.buddies[index].sub, tdata); 
     811    status = pjsip_pres_send_request(buddy->sub, tdata); 
    357812    if (status != PJ_SUCCESS) { 
    358         pjsip_pres_terminate(pjsua.buddies[index].sub, PJ_FALSE); 
    359         pjsua.buddies[index].sub = NULL; 
     813        pjsip_pres_terminate(buddy->sub, PJ_FALSE); 
     814        buddy->sub = NULL; 
    360815        pjsua_perror(THIS_FILE, "Unable to send initial SUBSCRIBE",  
    361816                     status); 
     
    368823static void unsubscribe_buddy_presence(unsigned index) 
    369824{ 
     825    pjsua_buddy *buddy; 
    370826    pjsip_tx_data *tdata; 
    371827    pj_status_t status; 
    372828 
    373     if (pjsua.buddies[index].sub == NULL) 
    374         return; 
    375  
    376     if (pjsip_evsub_get_state(pjsua.buddies[index].sub) ==  
    377         PJSIP_EVSUB_STATE_TERMINATED) 
    378     { 
    379         pjsua.buddies[index].sub = NULL; 
    380         return; 
    381     } 
    382  
    383     status = pjsip_pres_initiate( pjsua.buddies[index].sub, 0, &tdata); 
     829    buddy = &pjsua_var.buddy[index]; 
     830 
     831    if (buddy->sub == NULL) 
     832        return; 
     833 
     834    if (pjsip_evsub_get_state(buddy->sub) == PJSIP_EVSUB_STATE_TERMINATED) { 
     835        pjsua_var.buddy[index].sub = NULL; 
     836        return; 
     837    } 
     838 
     839    status = pjsip_pres_initiate( buddy->sub, 0, &tdata); 
    384840    if (status == PJ_SUCCESS) 
    385         status = pjsip_pres_send_request( pjsua.buddies[index].sub, tdata ); 
     841        status = pjsip_pres_send_request( buddy->sub, tdata ); 
    386842 
    387843    if (status != PJ_SUCCESS) { 
    388  
    389         pjsip_pres_terminate(pjsua.buddies[index].sub, PJ_FALSE); 
    390         pjsua.buddies[index].sub = NULL; 
     844        pjsip_pres_terminate(buddy->sub, PJ_FALSE); 
     845        buddy->sub = NULL; 
    391846        pjsua_perror(THIS_FILE, "Unable to unsubscribe presence",  
    392847                     status); 
     
    396851 
    397852/* It does what it says.. */ 
    398 static void refresh_client_subscription(void) 
     853static void refresh_client_subscriptions(void) 
    399854{ 
    400855    unsigned i; 
    401856 
    402     for (i=0; i<pjsua.config.buddy_cnt; ++i) { 
    403  
    404         if (pjsua.buddies[i].monitor && !pjsua.buddies[i].sub) { 
     857    for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.buddy); ++i) { 
     858 
     859        if (!pjsua_var.buddy[i].uri.slen) 
     860            continue; 
     861 
     862        if (pjsua_var.buddy[i].monitor && !pjsua_var.buddy[i].sub) { 
    405863            subscribe_buddy_presence(i); 
    406864 
    407         } else if (!pjsua.buddies[i].monitor && pjsua.buddies[i].sub) { 
     865        } else if (!pjsua_var.buddy[i].monitor && pjsua_var.buddy[i].sub) { 
    408866            unsubscribe_buddy_presence(i); 
    409867 
     
    418876pj_status_t pjsua_pres_init() 
    419877{ 
     878    unsigned i; 
    420879    pj_status_t status; 
    421880 
    422     status = pjsip_endpt_register_module( pjsua.endpt, &mod_pjsua_pres); 
     881    status = pjsip_endpt_register_module( pjsua_var.endpt, &mod_pjsua_pres); 
    423882    if (status != PJ_SUCCESS) { 
    424883        pjsua_perror(THIS_FILE, "Unable to register pjsua presence module",  
     
    426885    } 
    427886 
     887    for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.buddy); ++i) { 
     888        reset_buddy(i); 
     889    } 
     890 
    428891    return status; 
    429892} 
    430893 
    431 /* 
    432  * Get buddy count. 
    433  */ 
    434 PJ_DEF(unsigned) pjsua_get_buddy_count(void) 
    435 { 
    436     return pjsua.config.buddy_cnt; 
    437 } 
    438  
    439  
    440 /** 
    441  * Get buddy info. 
    442  */ 
    443 PJ_DEF(pj_status_t) pjsua_buddy_get_info(pjsua_buddy_id index, 
    444                                          pjsua_buddy_info *info) 
    445 { 
    446     pjsua_buddy *buddy; 
    447  
    448     PJ_ASSERT_RETURN(index < (int)PJ_ARRAY_SIZE(pjsua.config.buddy_uri),  
    449                      PJ_EINVAL); 
    450  
    451     pj_memset(info, 0, sizeof(pjsua_buddy_info)); 
    452  
    453     buddy = &pjsua.buddies[index]; 
    454     info->index = buddy->index; 
    455     info->is_valid = pjsua.config.buddy_uri[index].slen; 
    456     if (!info->is_valid) 
    457         return PJ_SUCCESS; 
    458  
    459     info->name = buddy->name; 
    460     info->display_name = buddy->display; 
    461     info->host = buddy->host; 
    462     info->port = buddy->port; 
    463     info->uri = pjsua.config.buddy_uri[index]; 
    464      
    465     if (buddy->sub == NULL || buddy->status.info_cnt==0) { 
    466         info->status = PJSUA_BUDDY_STATUS_UNKNOWN; 
    467         info->status_text = pj_str("?"); 
    468     } else if (pjsua.buddies[index].status.info[0].basic_open) { 
    469         info->status = PJSUA_BUDDY_STATUS_ONLINE; 
    470         info->status_text = pj_str("Online"); 
    471     } else { 
    472         info->status = PJSUA_BUDDY_STATUS_OFFLINE; 
    473         info->status_text = pj_str("Offline"); 
    474     } 
    475  
     894 
     895/* 
     896 * Start presence subsystem. 
     897 */ 
     898pj_status_t pjsua_pres_start(void) 
     899{ 
     900    /* Nothing to do (is it?) */ 
    476901    return PJ_SUCCESS; 
    477902} 
    478903 
    479904 
    480 /** 
    481  * Add new buddy. 
    482  */ 
    483 PJ_DEF(pj_status_t) pjsua_buddy_add( const pj_str_t *uri, 
    484                                      pjsua_buddy_id *buddy_index) 
    485 { 
    486     pjsip_name_addr *url; 
    487     pjsip_sip_uri *sip_uri; 
    488     int index; 
    489     pj_str_t tmp; 
    490  
    491     PJ_ASSERT_RETURN(pjsua.config.buddy_cnt <=  
    492                         PJ_ARRAY_SIZE(pjsua.config.buddy_uri), 
    493                      PJ_ETOOMANY); 
    494  
    495     /* Find empty slot */ 
    496     for (index=0; index<PJ_ARRAY_SIZE(pjsua.config.buddy_uri); ++index) { 
    497         if (pjsua.config.buddy_uri[index].slen == 0) 
    498             break; 
    499     } 
    500  
    501     /* Expect to find an empty slot */ 
    502     PJ_ASSERT_RETURN(index < PJ_ARRAY_SIZE(pjsua.config.buddy_uri), 
    503                      PJ_ETOOMANY); 
    504  
    505  
    506     /* Get name and display name for buddy */ 
    507     pj_strdup_with_null(pjsua.pool, &tmp, uri); 
    508     url = (pjsip_name_addr*)pjsip_parse_uri(pjsua.pool, tmp.ptr, tmp.slen, 
    509                                             PJSIP_PARSE_URI_AS_NAMEADDR); 
    510  
    511     if (url == NULL) 
    512         return PJSIP_EINVALIDURI; 
    513  
    514     /* Save URI */ 
    515     pjsua.config.buddy_uri[index] = tmp; 
    516  
    517     sip_uri = (pjsip_sip_uri*) url->uri; 
    518     pjsua.buddies[index].name = sip_uri->user; 
    519     pjsua.buddies[index].display = url->display; 
    520     pjsua.buddies[index].host = sip_uri->host; 
    521     pjsua.buddies[index].port = sip_uri->port; 
    522     if (pjsua.buddies[index].port == 0) 
    523         pjsua.buddies[index].port = 5060; 
    524  
    525     if (buddy_index) 
    526         *buddy_index = index; 
    527  
    528     pjsua.config.buddy_cnt++; 
    529  
    530     return PJ_SUCCESS; 
    531 } 
    532  
    533  
    534  
    535 /** 
    536  * Delete buddy. 
    537  */ 
    538 PJ_DEF(pj_status_t) pjsua_buddy_del(pjsua_buddy_id index) 
    539 { 
    540     PJ_ASSERT_RETURN(index < (int)PJ_ARRAY_SIZE(pjsua.config.buddy_uri),  
    541                      PJ_EINVAL); 
    542  
    543     if (pjsua.config.buddy_uri[index].slen == 0) 
    544         return PJ_SUCCESS; 
    545  
    546     /* Unsubscribe presence */ 
    547     pjsua_buddy_subscribe_pres(index, PJ_FALSE); 
    548  
    549     /* Remove buddy */ 
    550     pjsua.config.buddy_uri[index].slen = 0; 
    551     pjsua.config.buddy_cnt--; 
    552  
    553     return PJ_SUCCESS; 
    554 } 
    555  
    556  
    557 PJ_DEF(pj_status_t) pjsua_buddy_subscribe_pres( pjsua_buddy_id index, 
    558                                                 pj_bool_t monitor) 
    559 { 
    560     pjsua_buddy *buddy; 
    561  
    562     PJ_ASSERT_RETURN(index < (int)PJ_ARRAY_SIZE(pjsua.config.buddy_uri), 
    563                      PJ_EINVAL); 
    564  
    565     buddy = &pjsua.buddies[index]; 
    566     buddy->monitor = monitor; 
     905/* 
     906 * Refresh presence subscriptions 
     907 */ 
     908void pjsua_pres_refresh() 
     909{ 
     910    unsigned i; 
     911 
     912    refresh_client_subscriptions(); 
     913 
     914    for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.acc); ++i) { 
     915        if (pjsua_var.acc[i].valid) 
     916            refresh_server_subscription(i); 
     917    } 
     918} 
     919 
     920 
     921/* 
     922 * Shutdown presence. 
     923 */ 
     924void pjsua_pres_shutdown(void) 
     925{ 
     926    unsigned i; 
     927 
     928    for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.acc); ++i) { 
     929        if (!pjsua_var.acc[i].valid) 
     930            continue; 
     931        pjsua_pres_delete_acc(i); 
     932    } 
     933 
     934    for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.buddy); ++i) { 
     935        pjsua_var.buddy[i].monitor = 0; 
     936    } 
     937 
    567938    pjsua_pres_refresh(); 
    568     return PJ_SUCCESS; 
    569 } 
    570  
    571  
    572 PJ_DEF(pj_status_t) pjsua_acc_set_online_status( pjsua_acc_id acc_index, 
    573                                                  pj_bool_t is_online) 
    574 { 
    575     PJ_ASSERT_RETURN(acc_index < (int)PJ_ARRAY_SIZE(pjsua.acc),  
    576                      PJ_EINVAL); 
    577     PJ_ASSERT_RETURN(pjsua.acc[acc_index].valid, PJ_EINVALIDOP); 
    578  
    579     pjsua.acc[acc_index].online_status = is_online; 
    580     pjsua_pres_refresh(); 
    581     return PJ_SUCCESS; 
    582 } 
    583  
    584  
    585 /* 
    586  * Refresh presence 
    587  */ 
    588 PJ_DEF(void) pjsua_pres_refresh() 
    589 { 
    590     unsigned i; 
    591  
    592     refresh_client_subscription(); 
    593  
    594     for (i=0; i<PJ_ARRAY_SIZE(pjsua.acc); ++i) 
    595         refresh_server_subscription(i); 
    596 } 
    597  
    598  
    599 /* 
    600  * Shutdown presence. 
    601  */ 
    602 void pjsua_pres_shutdown(void) 
    603 { 
    604     unsigned acc_index; 
    605     unsigned i; 
    606  
    607     for (acc_index=0; acc_index<(int)pjsua.config.acc_cnt; ++acc_index) { 
    608         pjsua.acc[acc_index].online_status = 0; 
    609     } 
    610  
    611     for (i=0; i<pjsua.config.buddy_cnt; ++i) { 
    612         pjsua.buddies[i].monitor = 0; 
    613     } 
    614  
    615     pjsua_pres_refresh(); 
    616 } 
    617  
    618 /* 
    619  * Dump presence status. 
    620  */ 
    621 void pjsua_pres_dump(pj_bool_t detail) 
    622 { 
    623     unsigned acc_index; 
    624     unsigned i; 
    625  
    626  
    627     /* 
    628      * When no detail is required, just dump number of server and client 
    629      * subscriptions. 
    630      */ 
    631     if (detail == PJ_FALSE) { 
    632          
    633         int count = 0; 
    634  
    635         for (acc_index=0; acc_index < (int)pjsua.config.acc_cnt; ++acc_index) { 
    636  
    637             if (!pj_list_empty(&pjsua.acc[acc_index].pres_srv_list)) { 
    638                 struct pjsua_srv_pres *uapres; 
    639  
    640                 uapres = pjsua.acc[acc_index].pres_srv_list.next; 
    641                 while (uapres != &pjsua.acc[acc_index].pres_srv_list) { 
    642                     ++count; 
    643                     uapres = uapres->next; 
    644                 } 
    645             } 
    646         } 
    647  
    648         PJ_LOG(3,(THIS_FILE, "Number of server/UAS subscriptions: %d",  
    649                   count)); 
    650  
    651         count = 0; 
    652  
    653         for (i=0; i<pjsua.config.buddy_cnt; ++i) { 
    654             if (pjsua.buddies[i].sub) { 
    655                 ++count; 
    656             } 
    657         } 
    658  
    659         PJ_LOG(3,(THIS_FILE, "Number of client/UAC subscriptions: %d",  
    660                   count)); 
    661         return; 
    662     } 
    663      
    664  
    665     /* 
    666      * Dumping all server (UAS) subscriptions 
    667      */ 
    668     PJ_LOG(3,(THIS_FILE, "Dumping pjsua server subscriptions:")); 
    669  
    670     for (acc_index=0; acc_index < (int)pjsua.config.acc_cnt; ++acc_index) { 
    671  
    672         PJ_LOG(3,(THIS_FILE, "  %.*s", 
    673                   (int)pjsua.config.acc_config[acc_index].id.slen, 
    674                   pjsua.config.acc_config[acc_index].id.ptr)); 
    675  
    676         if (pj_list_empty(&pjsua.acc[acc_index].pres_srv_list)) { 
    677  
    678             PJ_LOG(3,(THIS_FILE, "  - none - ")); 
    679  
    680         } else { 
    681             struct pjsua_srv_pres *uapres; 
    682  
    683             uapres = pjsua.acc[acc_index].pres_srv_list.next; 
    684             while (uapres != &pjsua.acc[acc_index].pres_srv_list) { 
    685              
    686                 PJ_LOG(3,(THIS_FILE, "    %10s %s", 
    687                           pjsip_evsub_get_state_name(uapres->sub), 
    688                           uapres->remote)); 
    689  
    690                 uapres = uapres->next; 
    691             } 
    692         } 
    693     } 
    694  
    695     /* 
    696      * Dumping all client (UAC) subscriptions 
    697      */ 
    698     PJ_LOG(3,(THIS_FILE, "Dumping pjsua client subscriptions:")); 
    699  
    700     if (pjsua.config.buddy_cnt == 0) { 
    701  
    702         PJ_LOG(3,(THIS_FILE, "  - no buddy list - ")); 
    703  
    704     } else { 
    705         for (i=0; i<pjsua.config.buddy_cnt; ++i) { 
    706  
    707             if (pjsua.buddies[i].sub) { 
    708                 PJ_LOG(3,(THIS_FILE, "  %10s %.*s", 
    709                           pjsip_evsub_get_state_name(pjsua.buddies[i].sub), 
    710                           (int)pjsua.config.buddy_uri[i].slen, 
    711                           pjsua.config.buddy_uri[i].ptr)); 
    712             } else { 
    713                 PJ_LOG(3,(THIS_FILE, "  %10s %.*s", 
    714                           "(null)", 
    715                           (int)pjsua.config.buddy_uri[i].slen, 
    716                           pjsua.config.buddy_uri[i].ptr)); 
    717             } 
    718         } 
    719     } 
    720 } 
    721  
     939} 
Note: See TracChangeset for help on using the changeset viewer.