diff options
author | Benny Prijono <bennylp@teluu.com> | 2006-08-15 20:26:34 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2006-08-15 20:26:34 +0000 |
commit | 540278de72f88da8853d86dc3b655fe9bb3013b5 (patch) | |
tree | da69840039428b7daa2f1806d9d72eae13d51157 /pjsip/src/pjsua-lib/pjsua_pres.c | |
parent | ab77e4d8b4ddc20d6018d67c739e3317e4746c49 (diff) |
Support for PUBLISH (RFC 3903):
- API BREAK: pjsua_pres_create_uac() API CHANGED!! Added
options in the function, to allow creating SUBSCRIBE without
";id=" parameter in the Event header.
- the generic event publication in pjsip-simple/publish.[hc]
- split PIDF and X-PIDF body generation and parsing into
pjsip-simple/presence_body.c.
- allow NULL in module parameter in pjsip_endpt_add_capability()
- added "--publish" option in PJSUA.
- by default, PJSUA-LIB will not add ";id=" parameter in Event
header in the SUBSCRIBE request since lots of server and
user agents don't support this correctly.
- Set version to 0.5.7.6.
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@685 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjsip/src/pjsua-lib/pjsua_pres.c')
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_pres.c | 181 |
1 files changed, 176 insertions, 5 deletions
diff --git a/pjsip/src/pjsua-lib/pjsua_pres.c b/pjsip/src/pjsua-lib/pjsua_pres.c index ceb1b762..b3205cc5 100644 --- a/pjsip/src/pjsua-lib/pjsua_pres.c +++ b/pjsip/src/pjsua-lib/pjsua_pres.c @@ -566,14 +566,163 @@ static pj_bool_t pres_on_rx_request(pjsip_rx_data *rdata) } +/* + * Client presence publication callback. + */ +static void publish_cb(struct pjsip_publishc_cbparam *param) +{ + pjsua_acc *acc = param->token; + + if (param->code/100 != 2 || param->status != PJ_SUCCESS) { + if (param->status != PJ_SUCCESS) { + char errmsg[PJ_ERR_MSG_SIZE]; + + pj_strerror(param->status, errmsg, sizeof(errmsg)); + PJ_LOG(1,(THIS_FILE, + "Client publication (PUBLISH) failed, status=%d, msg=%s", + param->status, errmsg)); + } else { + PJ_LOG(1,(THIS_FILE, + "Client publication (PUBLISH) failed (%d/%.*s)", + param->code, (int)param->reason.slen, + param->reason.ptr)); + } + + pjsip_publishc_destroy(param->pubc); + acc->publish_sess = NULL; + } +} + + +/* + * Send PUBLISH request. + */ +static pj_status_t send_publish(int acc_id, pj_bool_t active) +{ + pjsua_acc_config *acc_cfg = &pjsua_var.acc[acc_id].cfg; + pjsua_acc *acc = &pjsua_var.acc[acc_id]; + pjsip_pres_status pres_status; + pjsip_tx_data *tdata; + pj_status_t status; + + + /* Create PUBLISH request */ + if (active) { + status = pjsip_publishc_publish(acc->publish_sess, PJ_TRUE, &tdata); + if (status != PJ_SUCCESS) { + pjsua_perror(THIS_FILE, "Error creating PUBLISH request", status); + goto on_error; + } + + /* Set our online status: */ + pj_bzero(&pres_status, sizeof(pres_status)); + pres_status.info_cnt = 1; + pres_status.info[0].basic_open = acc->online_status; + + /* Create and add PIDF message body */ + status = pjsip_pres_create_pidf(tdata->pool, &pres_status, + &acc_cfg->id, &tdata->msg->body); + if (status != PJ_SUCCESS) { + pjsua_perror(THIS_FILE, "Error creating PIDF for PUBLISH request", + status); + pjsip_tx_data_dec_ref(tdata); + goto on_error; + } + } else { + status = pjsip_publishc_unpublish(acc->publish_sess, &tdata); + if (status != PJ_SUCCESS) { + pjsua_perror(THIS_FILE, "Error creating PUBLISH request", status); + goto on_error; + } + } + + /* Add headers etc */ + pjsua_process_msg_data(tdata, NULL); + + /* Send the PUBLISH request */ + status = pjsip_publishc_send(acc->publish_sess, tdata); + if (status != PJ_SUCCESS) { + pjsua_perror(THIS_FILE, "Error sending PUBLISH request", status); + goto on_error; + } + + acc->publish_state = acc->online_status; + return PJ_SUCCESS; + +on_error: + pjsip_publishc_destroy(acc->publish_sess); + acc->publish_sess = NULL; + return status; +} + + +/* Create client publish session */ +static pj_status_t create_publish(int acc_id) +{ + const pj_str_t STR_PRESENCE = { "presence", 8 }; + pjsua_acc_config *acc_cfg = &pjsua_var.acc[acc_id].cfg; + pjsua_acc *acc = &pjsua_var.acc[acc_id]; + pj_status_t status; + + /* Create and init client publication session */ + if (acc_cfg->publish_enabled) { + + /* Create client publication */ + status = pjsip_publishc_create(pjsua_var.endpt, 0, acc, &publish_cb, + &acc->publish_sess); + if (status != PJ_SUCCESS) { + acc->publish_sess = NULL; + return status; + } + + /* Initialize client publication */ + status = pjsip_publishc_init(acc->publish_sess, &STR_PRESENCE, + &acc_cfg->id, &acc_cfg->id, + &acc_cfg->id, + PJSUA_PUBLISH_EXPIRATION); + if (status != PJ_SUCCESS) { + acc->publish_sess = NULL; + return status; + } + + /* Send initial PUBLISH request */ + if (acc->online_status != 0) { + status = send_publish(acc_id, PJ_TRUE); + if (status != PJ_SUCCESS) + return status; + } + + } else { + acc->publish_sess = NULL; + } + + return PJ_SUCCESS; +} + + +/* Init presence for account */ +pj_status_t pjsua_pres_init_acc(int acc_id) +{ + pjsua_acc *acc = &pjsua_var.acc[acc_id]; + + /* Init presence subscription */ + pj_list_init(&acc->pres_srv_list); + + + return create_publish(acc_id); +} + + /* Terminate server subscription for the account */ void pjsua_pres_delete_acc(int acc_id) { + pjsua_acc *acc = &pjsua_var.acc[acc_id]; + pjsua_acc_config *acc_cfg = &pjsua_var.acc[acc_id].cfg; pjsua_srv_pres *uapres; uapres = pjsua_var.acc[acc_id].pres_srv_list.next; - while (uapres != &pjsua_var.acc[acc_id].pres_srv_list) { + while (uapres != &acc->pres_srv_list) { pjsip_pres_status pres_status; pj_str_t reason = { "noresource", 10 }; @@ -593,24 +742,36 @@ void pjsua_pres_delete_acc(int acc_id) uapres = uapres->next; } + + if (acc->publish_sess) { + acc->online_status = PJ_FALSE; + send_publish(acc_id, PJ_FALSE); + if (acc->publish_sess) { + pjsip_publishc_destroy(acc->publish_sess); + acc->publish_sess = NULL; + } + acc_cfg->publish_enabled = PJ_FALSE; + } } /* Refresh subscription (e.g. when our online status has changed) */ static void refresh_server_subscription(int acc_id) { + pjsua_acc *acc = &pjsua_var.acc[acc_id]; + pjsua_acc_config *acc_cfg = &pjsua_var.acc[acc_id].cfg; pjsua_srv_pres *uapres; uapres = pjsua_var.acc[acc_id].pres_srv_list.next; - while (uapres != &pjsua_var.acc[acc_id].pres_srv_list) { + while (uapres != &acc->pres_srv_list) { pjsip_pres_status pres_status; pjsip_tx_data *tdata; pjsip_pres_get_status(uapres->sub, &pres_status); - if (pres_status.info[0].basic_open != pjsua_var.acc[acc_id].online_status) { - pres_status.info[0].basic_open = pjsua_var.acc[acc_id].online_status; + if (pres_status.info[0].basic_open != acc->online_status) { + pres_status.info[0].basic_open = acc->online_status; pjsip_pres_set_status(uapres->sub, &pres_status); if (pjsip_pres_current_notify(uapres->sub, &tdata)==PJ_SUCCESS) { @@ -621,6 +782,16 @@ static void refresh_server_subscription(int acc_id) uapres = uapres->next; } + + /* Send PUBLISH if required */ + if (acc_cfg->publish_enabled) { + if (acc->publish_sess == NULL) + create_publish(acc_id); + + if (acc->publish_sess && acc->publish_state != acc->online_status) { + send_publish(acc_id, PJ_TRUE); + } + } } @@ -819,7 +990,7 @@ static void subscribe_buddy_presence(unsigned index) } status = pjsip_pres_create_uac( dlg, &pres_callback, - &buddy->sub); + PJSIP_EVSUB_NO_EVENT_ID, &buddy->sub); if (status != PJ_SUCCESS) { pjsua_var.buddy[index].sub = NULL; pjsua_perror(THIS_FILE, "Unable to create presence client", |