Changeset 2150
- Timestamp:
- Jul 17, 2008 2:19:10 PM (16 years ago)
- Location:
- pjproject/trunk/pjsip
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
r2118 r2150 394 394 typedef int pjsua_conf_port_id; 395 395 396 /** Opaque declaration for server side presence subscription */ 397 typedef struct pjsua_srv_pres pjsua_srv_pres; 398 399 /** Forward declaration for pjsua_msg_data */ 400 typedef struct pjsua_msg_data pjsua_msg_data; 396 401 397 402 … … 792 797 */ 793 798 void (*on_reg_state)(pjsua_acc_id acc_id); 799 800 /** 801 * Notification when incoming SUBSCRIBE request is received. Application 802 * may use this callback to authorize the incoming subscribe request 803 * (e.g. ask user permission if the request should be granted). 804 * 805 * If this callback is not implemented, all incoming presence subscription 806 * requests will be accepted. 807 * 808 * If this callback is implemented, application has several choices on 809 * what to do with the incoming request: 810 * - it may reject the request immediately by specifying non-200 class 811 * final response in the \a code argument. 812 * - it may immediately accept the request by specifying 200 as the 813 * \a code argument. This is the default value if application doesn't 814 * set any value to the \a code argument. In this case, the library 815 * will automatically send NOTIFY request upon returning from this 816 * callback. 817 * - it may delay the processing of the request, for example to request 818 * user permission whether to accept or reject the request. In this 819 * case, the application MUST set the \a code argument to 202, and 820 * later calls #pjsua_pres_notify() to accept or reject the 821 * subscription request. 822 * 823 * Any \a code other than 200 and 202 will be treated as 200. 824 * 825 * Application MUST return from this callback immediately (e.g. it must 826 * not block in this callback while waiting for user confirmation). 827 * 828 * @param srv_pres Server presence subscription instance. If 829 * application delays the acceptance of the request, 830 * it will need to specify this object when calling 831 * #pjsua_pres_notify(). 832 * @param acc_id Account ID most appropriate for this request. 833 * @param buddy_id ID of the buddy matching the sender of the 834 * request, if any, or PJSUA_INVALID_ID if no 835 * matching buddy is found. 836 * @param from The From URI of the request. 837 * @param rdata The incoming request. 838 * @param code The status code to respond to the request. The 839 * default value is 200. Application may set this 840 * to other final status code to accept or reject 841 * the request. 842 * @param reason The reason phrase to respond to the request. 843 * @param msg_data If the application wants to send additional 844 * headers in the response, it can put it in this 845 * parameter. 846 */ 847 void (*on_incoming_subscribe)(pjsua_acc_id acc_id, 848 pjsua_srv_pres *srv_pres, 849 pjsua_buddy_id buddy_id, 850 const pj_str_t *from, 851 pjsip_rx_data *rdata, 852 pjsip_status_code *code, 853 pj_str_t *reason, 854 pjsua_msg_data *msg_data); 855 856 /** 857 * Notification when server side subscription state has changed. 858 * This callback is optional as application normally does not need 859 * to do anything to maintain server side presence subscription. 860 * 861 * @param acc_id The account ID. 862 * @param srv_pres Server presence subscription object. 863 * @param remote_uri Remote URI string. 864 * @param state New subscription state. 865 * @param event PJSIP event that triggers the state change. 866 */ 867 void (*on_srv_subscribe_state)(pjsua_acc_id acc_id, 868 pjsua_srv_pres *srv_pres, 869 const pj_str_t *remote_uri, 870 pjsip_evsub_state state, 871 pjsip_event *event); 794 872 795 873 /** … … 1194 1272 * \endcode 1195 1273 */ 1196 typedefstruct pjsua_msg_data1274 struct pjsua_msg_data 1197 1275 { 1198 1276 /** … … 1222 1300 pj_str_t msg_body; 1223 1301 1224 } pjsua_msg_data;1302 }; 1225 1303 1226 1304 … … 2412 2490 PJ_DECL(pj_status_t) pjsua_acc_set_registration(pjsua_acc_id acc_id, 2413 2491 pj_bool_t renew); 2414 2415 2492 2416 2493 /** … … 3353 3430 3354 3431 /** 3432 * If \a monitor_pres is enabled, this specifies the last state of the 3433 * presence subscription. If presence subscription session is currently 3434 * active, the value will be PJSIP_EVSUB_STATE_ACTIVE. If presence 3435 * subscription request has been rejected, the value will be 3436 * PJSIP_EVSUB_STATE_TERMINATED, and the termination reason will be 3437 * specified in \a sub_term_reason. 3438 */ 3439 pjsip_evsub_state sub_state; 3440 3441 /** 3442 * Specifies the last presence subscription terminatino reason. If 3443 * presence subscription is currently active, the value will be empty. 3444 */ 3445 pj_str_t sub_term_reason; 3446 3447 /** 3355 3448 * Extended RPID information about the person. 3356 3449 */ … … 3520 3613 PJ_DECL(pj_status_t) pjsua_buddy_update_pres(pjsua_buddy_id buddy_id); 3521 3614 3615 3616 /** 3617 * Send NOTIFY to inform account presence status or to terminate server 3618 * side presence subscription. If application wants to reject the incoming 3619 * request, it should set the \a state to PJSIP_EVSUB_STATE_TERMINATED. 3620 * 3621 * @param acc_id Account ID. 3622 * @param srv_pres Server presence subscription instance. 3623 * @param state New state to set. 3624 * @param state_str Optionally specify the state string name, if state 3625 * is not "active", "pending", or "terminated". 3626 * @param reason If the new state is PJSIP_EVSUB_STATE_TERMINATED, 3627 * optionally specify the termination reason. 3628 * @param with_body If the new state is PJSIP_EVSUB_STATE_TERMINATED, 3629 * this specifies whether the NOTIFY request should 3630 * contain message body containing account's presence 3631 * information. 3632 * @param msg_data Optional list of headers to be sent with the NOTIFY 3633 * request. 3634 * 3635 * @return PJ_SUCCESS on success. 3636 */ 3637 PJ_DECL(pj_status_t) pjsua_pres_notify(pjsua_acc_id acc_id, 3638 pjsua_srv_pres *srv_pres, 3639 pjsip_evsub_state state, 3640 const pj_str_t *state_str, 3641 const pj_str_t *reason, 3642 pj_bool_t with_body, 3643 const pjsua_msg_data *msg_data); 3522 3644 3523 3645 /** -
pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h
r2130 r2150 86 86 * Server presence subscription list head. 87 87 */ 88 typedefstruct pjsua_srv_pres88 struct pjsua_srv_pres 89 89 { 90 90 PJ_DECL_LIST_MEMBER(struct pjsua_srv_pres); 91 pjsip_evsub *sub; 92 char *remote; 93 } pjsua_srv_pres; 91 pjsip_evsub *sub; /**< The evsub. */ 92 char *remote; /**< Remote URI. */ 93 int acc_id; /**< Account ID. */ 94 pjsip_dialog *dlg; /**< Dialog. */ 95 int expires; /**< "expires" value in the request. */ 96 }; 94 97 95 98 … … 151 154 } pjsua_transport_data; 152 155 156 157 /** Maximum length of subscription termination reason. */ 158 #define PJSUA_BUDDY_SUB_TERM_REASON_LEN 32 153 159 154 160 /** … … 168 174 pjsip_dialog *dlg; /**< The underlying dialog. */ 169 175 pjsip_evsub *sub; /**< Buddy presence subscription */ 176 pj_str_t term_reason;/**< Subscription termination reason */ 170 177 pjsip_pres_status status; /**< Buddy presence status. */ 171 178 -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_pres.c
r2130 r2150 164 164 info->monitor_pres = buddy->monitor; 165 165 166 /* subscription state and termination reason */ 167 if (buddy->sub) { 168 info->sub_state = pjsip_evsub_get_state(buddy->sub); 169 if (info->sub_state == PJSIP_EVSUB_STATE_TERMINATED && 170 total < sizeof(info->buf_)) 171 { 172 info->sub_term_reason.ptr = info->buf_ + total; 173 pj_strncpy(&info->sub_term_reason, 174 pjsip_evsub_get_termination_reason(buddy->sub), 175 sizeof(info->buf_) - total); 176 total += info->sub_term_reason.slen; 177 } else { 178 info->sub_term_reason = pj_str(""); 179 } 180 } else if (total < sizeof(info->buf_)) { 181 info->sub_term_reason.ptr = info->buf_ + total; 182 pj_strncpy(&info->sub_term_reason, &buddy->term_reason, 183 sizeof(info->buf_) - total); 184 total += info->sub_term_reason.slen; 185 } else { 186 info->sub_term_reason = pj_str(""); 187 } 188 166 189 PJSUA_UNLOCK(); 167 190 return PJ_SUCCESS; … … 223 246 buddy->pool = pjsua_pool_create(name, 512, 256); 224 247 } 248 249 /* Init buffers for presence subscription status */ 250 buddy->term_reason.ptr = (char*) 251 pj_pool_alloc(buddy->pool, 252 PJSUA_BUDDY_SUB_TERM_REASON_LEN); 225 253 226 254 /* Get name and display name for buddy */ … … 525 553 uapres = (pjsua_srv_pres*) pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id); 526 554 if (uapres) { 555 pjsip_evsub_state state; 556 527 557 PJ_LOG(4,(THIS_FILE, "Server subscription to %s is %s", 528 558 uapres->remote, pjsip_evsub_get_state_name(sub))); 529 559 530 if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) { 560 state = pjsip_evsub_get_state(sub); 561 562 if (pjsua_var.ua_cfg.cb.on_srv_subscribe_state) { 563 pj_str_t from; 564 565 from = uapres->dlg->remote.info_str; 566 (*pjsua_var.ua_cfg.cb.on_srv_subscribe_state)(uapres->acc_id, 567 uapres, &from, 568 state, event); 569 } 570 571 if (state == PJSIP_EVSUB_STATE_TERMINATED) { 531 572 pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, NULL); 532 573 pj_list_erase(uapres); … … 549 590 pjsip_evsub *sub; 550 591 pjsip_evsub_user pres_cb; 551 pjsip_tx_data *tdata;552 pjsip_pres_status pres_status;553 592 pjsip_dialog *dlg; 593 pjsip_status_code st_code; 594 pj_str_t reason; 554 595 pjsip_expires_hdr *expires_hdr; 555 pjsip_evsub_state ev_state; 556 pjsua_buddy_id buddy_id; 596 pjsua_msg_data msg_data; 557 597 pj_status_t status; 558 598 … … 628 668 uapres->sub = sub; 629 669 uapres->remote = (char*) pj_pool_alloc(dlg->pool, PJSIP_MAX_URL_SIZE); 670 uapres->acc_id = acc_id; 671 uapres->dlg = dlg; 630 672 status = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, dlg->remote.info->uri, 631 673 uapres->remote, PJSIP_MAX_URL_SIZE); … … 641 683 642 684 643 /* Create and send 200 (OK) to the SUBSCRIBE request: */ 644 status = pjsip_pres_accept(sub, rdata, 200, NULL); 685 /* Capture the value of Expires header. */ 686 expires_hdr = (pjsip_expires_hdr*) 687 pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, 688 NULL); 689 if (expires_hdr) 690 uapres->expires = expires_hdr->ivalue; 691 else 692 uapres->expires = -1; 693 694 st_code = 200; 695 reason = pj_str("OK"); 696 pjsua_msg_data_init(&msg_data); 697 698 /* Notify application callback, if any */ 699 if (pjsua_var.ua_cfg.cb.on_incoming_subscribe) { 700 pjsua_buddy_id buddy_id; 701 702 buddy_id = pjsua_find_buddy(rdata->msg_info.from->uri); 703 704 (*pjsua_var.ua_cfg.cb.on_incoming_subscribe)(acc_id, uapres, buddy_id, 705 &dlg->remote.info_str, 706 rdata, &st_code, &reason, 707 &msg_data); 708 } 709 710 /* Handle rejection case */ 711 if (st_code >= 300) { 712 pjsip_tx_data *tdata; 713 714 /* Create response */ 715 status = pjsip_dlg_create_response(dlg, rdata, st_code, 716 &reason, &tdata); 717 if (status != PJ_SUCCESS) { 718 pjsua_perror(THIS_FILE, "Error creating response", status); 719 pj_list_erase(uapres); 720 pjsip_pres_terminate(sub, PJ_FALSE); 721 PJSUA_UNLOCK(); 722 return PJ_FALSE; 723 } 724 725 /* Add header list, if any */ 726 pjsua_process_msg_data(tdata, &msg_data); 727 728 /* Send the response */ 729 status = pjsip_dlg_send_response(dlg, pjsip_rdata_get_tsx(rdata), 730 tdata); 731 if (status != PJ_SUCCESS) { 732 pjsua_perror(THIS_FILE, "Error sending response", status); 733 /* This is not fatal */ 734 } 735 736 /* Terminate presence subscription */ 737 pj_list_erase(uapres); 738 pjsip_pres_terminate(sub, PJ_FALSE); 739 PJSUA_UNLOCK(); 740 return PJ_TRUE; 741 } 742 743 /* Create and send 2xx response to the SUBSCRIBE request: */ 744 status = pjsip_pres_accept(sub, rdata, st_code, &msg_data.hdr_list); 645 745 if (status != PJ_SUCCESS) { 646 746 pjsua_perror(THIS_FILE, "Unable to accept presence subscription", … … 652 752 } 653 753 754 /* If code is 200, send NOTIFY now */ 755 if (st_code == 200) { 756 pjsua_pres_notify(acc_id, uapres, PJSIP_EVSUB_STATE_ACTIVE, 757 NULL, NULL, PJ_TRUE, &msg_data); 758 } 759 760 /* Done: */ 761 762 PJSUA_UNLOCK(); 763 764 return PJ_TRUE; 765 } 766 767 768 /* 769 * Send NOTIFY. 770 */ 771 PJ_DEF(pj_status_t) pjsua_pres_notify( pjsua_acc_id acc_id, 772 pjsua_srv_pres *srv_pres, 773 pjsip_evsub_state ev_state, 774 const pj_str_t *state_str, 775 const pj_str_t *reason, 776 pj_bool_t with_body, 777 const pjsua_msg_data *msg_data) 778 { 779 pjsua_acc *acc; 780 pjsip_pres_status pres_status; 781 pjsua_buddy_id buddy_id; 782 pjsip_tx_data *tdata; 783 pj_status_t status; 784 785 /* Check parameters */ 786 PJ_ASSERT_RETURN(acc_id!=-1 && srv_pres, PJ_EINVAL); 787 788 /* Check that account ID is valid */ 789 PJ_ASSERT_RETURN(acc_id>=0 && acc_id<(int)PJ_ARRAY_SIZE(pjsua_var.acc), 790 PJ_EINVAL); 791 /* Check that account is valid */ 792 PJ_ASSERT_RETURN(pjsua_var.acc[acc_id].valid, PJ_EINVALIDOP); 793 794 PJSUA_LOCK(); 795 796 acc = &pjsua_var.acc[acc_id]; 797 798 /* Check that the server presence subscription is still valid */ 799 if (pj_list_find_node(&acc->pres_srv_list, srv_pres) == NULL) { 800 /* Subscription has been terminated */ 801 PJSUA_UNLOCK(); 802 return PJ_EINVALIDOP; 803 } 654 804 655 805 /* Set our online status: */ 656 806 pj_bzero(&pres_status, sizeof(pres_status)); 657 807 pres_status.info_cnt = 1; 658 pres_status.info[0].basic_open = pjsua_var.acc[acc_id].online_status;659 pres_status.info[0].id = pjsua_var.acc[acc_id].cfg.pidf_tuple_id;808 pres_status.info[0].basic_open = acc->online_status; 809 pres_status.info[0].id = acc->cfg.pidf_tuple_id; 660 810 //Both pjsua_var.local_uri and pjsua_var.contact_uri are enclosed in "<" and ">" 661 811 //causing XML parsing to fail. 662 812 //pres_status.info[0].contact = pjsua_var.local_uri; 663 813 664 pjsip_pres_set_status(s ub, &pres_status);814 pjsip_pres_set_status(srv_pres->sub, &pres_status); 665 815 666 816 /* Check expires value. If it's zero, send our presense state but 667 817 * set subscription state to TERMINATED. 668 818 */ 669 expires_hdr=(pjsip_expires_hdr*) 670 pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, NULL); 671 672 if (expires_hdr && expires_hdr->ivalue == 0) 819 if (srv_pres->expires == 0) 673 820 ev_state = PJSIP_EVSUB_STATE_TERMINATED; 674 else 675 ev_state = PJSIP_EVSUB_STATE_ACTIVE; 676 677 /* Create and send the first NOTIFY to active subscription: */ 678 status = pjsip_pres_notify( sub, ev_state, NULL, NULL, &tdata); 821 822 /* Create and send the NOTIFY to active subscription: */ 823 status = pjsip_pres_notify(srv_pres->sub, ev_state, state_str, 824 reason, &tdata); 679 825 if (status == PJ_SUCCESS) { 680 pjsua_process_msg_data(tdata, NULL); 681 status = pjsip_pres_send_request( sub, tdata); 826 /* Force removal of message body if msg_body==FALSE */ 827 if (!with_body) { 828 tdata->msg->body = NULL; 829 } 830 pjsua_process_msg_data(tdata, msg_data); 831 status = pjsip_pres_send_request( srv_pres->sub, tdata); 682 832 } 683 833 … … 685 835 pjsua_perror(THIS_FILE, "Unable to create/send NOTIFY", 686 836 status); 687 pj_list_erase( uapres);688 pjsip_pres_terminate(s ub, PJ_FALSE);689 PJSUA_UNLOCK(); 690 return PJ_FALSE;837 pj_list_erase(srv_pres); 838 pjsip_pres_terminate(srv_pres->sub, PJ_FALSE); 839 PJSUA_UNLOCK(); 840 return status; 691 841 } 692 842 693 843 694 844 /* Subscribe to buddy's presence if we're not subscribed */ 695 buddy_id = pjsua_find_buddy( dlg->remote.info->uri);845 buddy_id = pjsua_find_buddy(srv_pres->dlg->remote.info->uri); 696 846 if (buddy_id != PJSUA_INVALID_ID) { 697 847 pjsua_buddy *b = &pjsua_var.buddy[buddy_id]; … … 703 853 } 704 854 705 /* Done: */706 707 855 PJSUA_UNLOCK(); 708 856 709 return PJ_ TRUE;857 return PJ_SUCCESS; 710 858 } 711 859 … … 1010 1158 1011 1159 if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) { 1160 if (buddy->term_reason.ptr == NULL) { 1161 buddy->term_reason.ptr = (char*) 1162 pj_pool_alloc(buddy->pool, 1163 PJSUA_BUDDY_SUB_TERM_REASON_LEN); 1164 } 1165 pj_strncpy(&buddy->term_reason, 1166 pjsip_evsub_get_termination_reason(sub), 1167 PJSUA_BUDDY_SUB_TERM_REASON_LEN); 1168 } else { 1169 buddy->term_reason.slen = 0; 1170 } 1171 1172 /* Call callback */ 1173 if (pjsua_var.ua_cfg.cb.on_buddy_state) 1174 (*pjsua_var.ua_cfg.cb.on_buddy_state)(buddy->index); 1175 1176 /* Clear subscription */ 1177 if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) { 1012 1178 buddy->sub = NULL; 1013 1179 buddy->status.info_cnt = 0; 1014 1180 pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, NULL); 1015 1181 } 1016 1017 /* Call callback */1018 if (pjsua_var.ua_cfg.cb.on_buddy_state)1019 (*pjsua_var.ua_cfg.cb.on_buddy_state)(buddy->index);1020 1182 } 1021 1183
Note: See TracChangeset
for help on using the changeset viewer.