From a08b589d09d5197f9a76d549a189e4686bd2ca8c Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Sun, 13 Nov 2005 19:40:44 +0000 Subject: Applying license to pjproject git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@49 74dad513-b988-da41-8d7b-12977e46ad98 --- pjsip/src/pjsip-simple/presence.c | 790 ++++++++++++++++++++------------------ 1 file changed, 406 insertions(+), 384 deletions(-) (limited to 'pjsip/src/pjsip-simple/presence.c') diff --git a/pjsip/src/pjsip-simple/presence.c b/pjsip/src/pjsip-simple/presence.c index 32ed8e3c..5f5893ac 100644 --- a/pjsip/src/pjsip-simple/presence.c +++ b/pjsip/src/pjsip-simple/presence.c @@ -1,384 +1,406 @@ -/* $Id$ - * - */ -#include -#include -#include -#include -#include -#include -#include - -/* Forward declarations. */ -static void on_query_subscribe(pjsip_rx_data *rdata, int *status); -static void on_subscribe(pjsip_event_sub *sub, pjsip_rx_data *rdata, - pjsip_event_sub_cb **cb, int *expires); -static void on_sub_terminated(pjsip_event_sub *sub, const pj_str_t *reason); -static void on_sub_received_refresh(pjsip_event_sub *sub, pjsip_rx_data *rdata); -static void on_received_notify(pjsip_event_sub *sub, pjsip_rx_data *rdata); - -/* Some string constants. */ -static pj_str_t PRESENCE_EVENT = { "presence", 8 }; - -/* Accept types. */ -static pj_str_t accept_names[] = { - { "application/pidf+xml", 20 }, - { "application/xpidf+xml", 21 } -}; -static pjsip_media_type accept_types[] = { - { - { "application", 11 }, - { "pidf+xml", 8 } - }, - { - { "application", 11 }, - { "xpidf+xml", 9 } - } -}; - -/* Callback that is registered by application. */ -static pjsip_presence_cb cb; - -/* Package callback to be register to event_notify */ -static pjsip_event_sub_pkg_cb pkg_cb = { &on_query_subscribe, - &on_subscribe }; - -/* Global/static callback to be registered to event_notify */ -static pjsip_event_sub_cb sub_cb = { &on_sub_terminated, - &on_sub_received_refresh, - NULL, - &on_received_notify, - NULL }; - -/* - * Initialize presence module. - * This will register event package "presence" to event framework. - */ -PJ_DEF(void) pjsip_presence_init(const pjsip_presence_cb *pcb) -{ - pj_memcpy(&cb, pcb, sizeof(*pcb)); - pjsip_event_sub_register_pkg( &PRESENCE_EVENT, - sizeof(accept_names)/sizeof(accept_names[0]), - accept_names, - &pkg_cb); -} - -/* - * Create presence subscription. - */ -PJ_DEF(pjsip_presentity*) pjsip_presence_create( pjsip_endpoint *endpt, - const pj_str_t *local_url, - const pj_str_t *remote_url, - int expires, - void *user_data ) -{ - pjsip_event_sub *sub; - pjsip_presentity *pres; - - if (expires < 0) - expires = 300; - - /* Create event subscription */ - sub = pjsip_event_sub_create(endpt, local_url, remote_url, &PRESENCE_EVENT, - expires, - sizeof(accept_names)/sizeof(accept_names[0]), - accept_names, - NULL, &sub_cb); - if (!sub) - return NULL; - - /* Allocate presence descriptor. */ - pres = pj_pool_calloc(sub->pool, 1, sizeof(*pres)); - pres->sub = sub; - pres->user_data = user_data; - sub->user_data = pres; - - return pres; -} - -/* - * Send SUBSCRIBE. - */ -PJ_DEF(pj_status_t) pjsip_presence_subscribe( pjsip_presentity *pres ) -{ - return pjsip_event_sub_subscribe( pres->sub ); -} - -/* - * Set credentials to be used for outgoing requests. - */ -PJ_DEF(pj_status_t) pjsip_presence_set_credentials( pjsip_presentity *pres, - int count, - const pjsip_cred_info cred[]) -{ - return pjsip_event_sub_set_credentials(pres->sub, count, cred); -} - -/* - * Set route-set. - */ -PJ_DEF(pj_status_t) pjsip_presence_set_route_set( pjsip_presentity *pres, - const pjsip_route_hdr *hdr ) -{ - return pjsip_event_sub_set_route_set( pres->sub, hdr ); -} - -/* - * Unsubscribe. - */ -PJ_DEF(pj_status_t) pjsip_presence_unsubscribe( pjsip_presentity *pres ) -{ - return pjsip_event_sub_unsubscribe(pres->sub); -} - -/* - * This is the pjsip_msg_body callback to print XML body. - */ -static int print_xml(pjsip_msg_body *body, char *buf, pj_size_t size) -{ - return pj_xml_print( body->data, buf, size, PJ_TRUE ); -} - -/* - * Create and initialize PIDF document and msg body (notifier only). - */ -static pj_status_t init_presence_info( pjsip_presentity *pres ) -{ - pj_str_t uri; - pj_pool_t *pool = pres->sub->pool; - char tmp[PJSIP_MAX_URL_SIZE]; - pjpidf_tuple *tuple; - const pjsip_media_type *content_type = NULL; - - pj_assert(pres->uas_body == NULL); - - /* Make entity_id */ - uri.ptr = tmp; - uri.slen = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, pres->sub->from->uri, - tmp, sizeof(tmp)); - if (uri.slen < 0) - return -1; - - if (pres->pres_type == PJSIP_PRES_TYPE_PIDF) { - pj_str_t s; - - /* Create . */ - pres->uas_data.pidf = pjpidf_create(pool, &s); - - /* Create */ - pj_create_unique_string(pool, &s); - tuple = pjpidf_pres_add_tuple(pool, pres->uas_data.pidf, &s); - - /* Set */ - s.ptr = tmp; - s.slen = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, pres->sub->contact->uri, tmp, sizeof(tmp)); - if (s.slen < 0) - return -1; - pjpidf_tuple_set_contact(pool, tuple, &s); - - /* Content-Type */ - content_type = &accept_types[PJSIP_PRES_TYPE_PIDF]; - - } else if (pres->pres_type == PJSIP_PRES_TYPE_XPIDF) { - - /* Create XPIDF */ - pres->uas_data.xpidf = pjxpidf_create(pool, &uri); - - /* Content-Type. */ - content_type = &accept_types[PJSIP_PRES_TYPE_XPIDF]; - } - - /* Create message body */ - pres->uas_body = pj_pool_alloc(pool, sizeof(pjsip_msg_body)); - pres->uas_body->content_type = *content_type; - pres->uas_body->data = pres->uas_data.pidf; - pres->uas_body->len = 0; - pres->uas_body->print_body = &print_xml; - - return 0; -} - -/* - * Send NOTIFY and set subscription state. - */ -PJ_DEF(pj_status_t) pjsip_presence_notify( pjsip_presentity *pres, - pjsip_event_sub_state state, - pj_bool_t is_online ) -{ - pj_str_t reason = { "", 0 }; - - if (pres->uas_data.pidf == NULL) { - if (init_presence_info(pres) != 0) - return -1; - } - - /* Update basic status in PIDF/XPIDF document. */ - if (pres->pres_type == PJSIP_PRES_TYPE_PIDF) { - pjpidf_tuple *first; - pjpidf_status *status; - pj_time_val now; - pj_parsed_time pnow; - - first = pjpidf_op.pres.get_first_tuple(pres->uas_data.pidf); - pj_assert(first); - status = pjpidf_op.tuple.get_status(first); - pj_assert(status); - pjpidf_op.status.set_basic_open(status, is_online); - - /* Update timestamp. */ - if (pres->timestamp.ptr == 0) { - pres->timestamp.ptr = pj_pool_alloc(pres->sub->pool, 24); - } - pj_gettimeofday(&now); - pj_time_decode(&now, &pnow); - pres->timestamp.slen = sprintf(pres->timestamp.ptr, - "%04d-%02d-%02dT%02d:%02d:%02dZ", - pnow.year, pnow.mon, pnow.day, - pnow.hour, pnow.min, pnow.sec); - pjpidf_op.tuple.set_timestamp_np(pres->sub->pool, first, &pres->timestamp); - - } else if (pres->pres_type == PJSIP_PRES_TYPE_XPIDF) { - pjxpidf_set_status( pres->uas_data.xpidf, is_online ); - - } else { - pj_assert(0); - } - - /* Send notify. */ - return pjsip_event_sub_notify( pres->sub, state, &reason, pres->uas_body); -} - -/* - * Destroy subscription (can be called for both subscriber and notifier). - */ -PJ_DEF(pj_status_t) pjsip_presence_destroy( pjsip_presentity *pres ) -{ - return pjsip_event_sub_destroy(pres->sub); -} - -/* - * This callback is called by event framework to query whether we want to - * accept an incoming subscription. - */ -static void on_query_subscribe(pjsip_rx_data *rdata, int *status) -{ - if (cb.accept_presence) { - (*cb.accept_presence)(rdata, status); - } -} - -/* - * This callback is called by event framework after we accept the incoming - * subscription, to notify about the new subscription instance. - */ -static void on_subscribe(pjsip_event_sub *sub, pjsip_rx_data *rdata, - pjsip_event_sub_cb **set_sub_cb, int *expires) -{ - pjsip_presentity *pres; - pjsip_accept_hdr *accept; - - pres = pj_pool_calloc(sub->pool, 1, sizeof(*pres)); - pres->sub = sub; - pres->pres_type = PJSIP_PRES_TYPE_PIDF; - sub->user_data = pres; - *set_sub_cb = &sub_cb; - - accept = pjsip_msg_find_hdr(rdata->msg, PJSIP_H_ACCEPT, NULL); - if (accept) { - unsigned i; - int found = 0; - for (i=0; icount && !found; ++i) { - int j; - for (j=0; jvalues[i], &accept_names[j])) { - pres->pres_type = j; - found = 1; - break; - } - } - } - pj_assert(found ); - } - - (*cb.on_received_request)(pres, rdata, expires); -} - -/* - * This callback is called by event framework when the subscription is - * terminated. - */ -static void on_sub_terminated(pjsip_event_sub *sub, const pj_str_t *reason) -{ - pjsip_presentity *pres = sub->user_data; - if (cb.on_terminated) - (*cb.on_terminated)(pres, reason); -} - -/* - * This callback is called by event framework when it receives incoming - * SUBSCRIBE request to refresh the subscription. - */ -static void on_sub_received_refresh(pjsip_event_sub *sub, pjsip_rx_data *rdata) -{ - pjsip_presentity *pres = sub->user_data; - if (cb.on_received_refresh) - (*cb.on_received_refresh)(pres, rdata); -} - -/* - * This callback is called by event framework when it receives incoming - * NOTIFY request. - */ -static void on_received_notify(pjsip_event_sub *sub, pjsip_rx_data *rdata) -{ - pjsip_presentity *pres = sub->user_data; - - if (cb.on_received_update) { - pj_status_t is_open; - pjsip_msg_body *body; - int i; - - body = rdata->msg->body; - if (!body) - return; - - for (i=0; icontent_type.type, &accept_types[i].type) && - !pj_stricmp(&body->content_type.subtype, &accept_types[i].subtype)) - { - break; - } - } - - if (i==PJSIP_PRES_TYPE_PIDF) { - pjpidf_pres *pres; - pjpidf_tuple *tuple; - pjpidf_status *status; - - pres = pjpidf_parse(rdata->pool, body->data, body->len); - if (!pres) - return; - tuple = pjpidf_pres_get_first_tuple(pres); - if (!tuple) - return; - status = pjpidf_tuple_get_status(tuple); - if (!status) - return; - is_open = pjpidf_status_is_basic_open(status); - - } else if (i==PJSIP_PRES_TYPE_XPIDF) { - pjxpidf_pres *pres; - - pres = pjxpidf_parse(rdata->pool, body->data, body->len); - if (!pres) - return; - is_open = pjxpidf_get_status(pres); - - } else { - return; - } - - (*cb.on_received_update)(pres, is_open); - } -} - +/* $Id$ + * + */ +/* + * PJSIP - SIP Stack + * (C)2003-2005 Benny Prijono + * + * Author: + * Benny Prijono + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#include +#include +#include +#include +#include +#include +#include + +/* Forward declarations. */ +static void on_query_subscribe(pjsip_rx_data *rdata, int *status); +static void on_subscribe(pjsip_event_sub *sub, pjsip_rx_data *rdata, + pjsip_event_sub_cb **cb, int *expires); +static void on_sub_terminated(pjsip_event_sub *sub, const pj_str_t *reason); +static void on_sub_received_refresh(pjsip_event_sub *sub, pjsip_rx_data *rdata); +static void on_received_notify(pjsip_event_sub *sub, pjsip_rx_data *rdata); + +/* Some string constants. */ +static pj_str_t PRESENCE_EVENT = { "presence", 8 }; + +/* Accept types. */ +static pj_str_t accept_names[] = { + { "application/pidf+xml", 20 }, + { "application/xpidf+xml", 21 } +}; +static pjsip_media_type accept_types[] = { + { + { "application", 11 }, + { "pidf+xml", 8 } + }, + { + { "application", 11 }, + { "xpidf+xml", 9 } + } +}; + +/* Callback that is registered by application. */ +static pjsip_presence_cb cb; + +/* Package callback to be register to event_notify */ +static pjsip_event_sub_pkg_cb pkg_cb = { &on_query_subscribe, + &on_subscribe }; + +/* Global/static callback to be registered to event_notify */ +static pjsip_event_sub_cb sub_cb = { &on_sub_terminated, + &on_sub_received_refresh, + NULL, + &on_received_notify, + NULL }; + +/* + * Initialize presence module. + * This will register event package "presence" to event framework. + */ +PJ_DEF(void) pjsip_presence_init(const pjsip_presence_cb *pcb) +{ + pj_memcpy(&cb, pcb, sizeof(*pcb)); + pjsip_event_sub_register_pkg( &PRESENCE_EVENT, + sizeof(accept_names)/sizeof(accept_names[0]), + accept_names, + &pkg_cb); +} + +/* + * Create presence subscription. + */ +PJ_DEF(pjsip_presentity*) pjsip_presence_create( pjsip_endpoint *endpt, + const pj_str_t *local_url, + const pj_str_t *remote_url, + int expires, + void *user_data ) +{ + pjsip_event_sub *sub; + pjsip_presentity *pres; + + if (expires < 0) + expires = 300; + + /* Create event subscription */ + sub = pjsip_event_sub_create(endpt, local_url, remote_url, &PRESENCE_EVENT, + expires, + sizeof(accept_names)/sizeof(accept_names[0]), + accept_names, + NULL, &sub_cb); + if (!sub) + return NULL; + + /* Allocate presence descriptor. */ + pres = pj_pool_calloc(sub->pool, 1, sizeof(*pres)); + pres->sub = sub; + pres->user_data = user_data; + sub->user_data = pres; + + return pres; +} + +/* + * Send SUBSCRIBE. + */ +PJ_DEF(pj_status_t) pjsip_presence_subscribe( pjsip_presentity *pres ) +{ + return pjsip_event_sub_subscribe( pres->sub ); +} + +/* + * Set credentials to be used for outgoing requests. + */ +PJ_DEF(pj_status_t) pjsip_presence_set_credentials( pjsip_presentity *pres, + int count, + const pjsip_cred_info cred[]) +{ + return pjsip_event_sub_set_credentials(pres->sub, count, cred); +} + +/* + * Set route-set. + */ +PJ_DEF(pj_status_t) pjsip_presence_set_route_set( pjsip_presentity *pres, + const pjsip_route_hdr *hdr ) +{ + return pjsip_event_sub_set_route_set( pres->sub, hdr ); +} + +/* + * Unsubscribe. + */ +PJ_DEF(pj_status_t) pjsip_presence_unsubscribe( pjsip_presentity *pres ) +{ + return pjsip_event_sub_unsubscribe(pres->sub); +} + +/* + * This is the pjsip_msg_body callback to print XML body. + */ +static int print_xml(pjsip_msg_body *body, char *buf, pj_size_t size) +{ + return pj_xml_print( body->data, buf, size, PJ_TRUE ); +} + +/* + * Create and initialize PIDF document and msg body (notifier only). + */ +static pj_status_t init_presence_info( pjsip_presentity *pres ) +{ + pj_str_t uri; + pj_pool_t *pool = pres->sub->pool; + char tmp[PJSIP_MAX_URL_SIZE]; + pjpidf_tuple *tuple; + const pjsip_media_type *content_type = NULL; + + pj_assert(pres->uas_body == NULL); + + /* Make entity_id */ + uri.ptr = tmp; + uri.slen = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, pres->sub->from->uri, + tmp, sizeof(tmp)); + if (uri.slen < 0) + return -1; + + if (pres->pres_type == PJSIP_PRES_TYPE_PIDF) { + pj_str_t s; + + /* Create . */ + pres->uas_data.pidf = pjpidf_create(pool, &s); + + /* Create */ + pj_create_unique_string(pool, &s); + tuple = pjpidf_pres_add_tuple(pool, pres->uas_data.pidf, &s); + + /* Set */ + s.ptr = tmp; + s.slen = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, pres->sub->contact->uri, tmp, sizeof(tmp)); + if (s.slen < 0) + return -1; + pjpidf_tuple_set_contact(pool, tuple, &s); + + /* Content-Type */ + content_type = &accept_types[PJSIP_PRES_TYPE_PIDF]; + + } else if (pres->pres_type == PJSIP_PRES_TYPE_XPIDF) { + + /* Create XPIDF */ + pres->uas_data.xpidf = pjxpidf_create(pool, &uri); + + /* Content-Type. */ + content_type = &accept_types[PJSIP_PRES_TYPE_XPIDF]; + } + + /* Create message body */ + pres->uas_body = pj_pool_alloc(pool, sizeof(pjsip_msg_body)); + pres->uas_body->content_type = *content_type; + pres->uas_body->data = pres->uas_data.pidf; + pres->uas_body->len = 0; + pres->uas_body->print_body = &print_xml; + + return 0; +} + +/* + * Send NOTIFY and set subscription state. + */ +PJ_DEF(pj_status_t) pjsip_presence_notify( pjsip_presentity *pres, + pjsip_event_sub_state state, + pj_bool_t is_online ) +{ + pj_str_t reason = { "", 0 }; + + if (pres->uas_data.pidf == NULL) { + if (init_presence_info(pres) != 0) + return -1; + } + + /* Update basic status in PIDF/XPIDF document. */ + if (pres->pres_type == PJSIP_PRES_TYPE_PIDF) { + pjpidf_tuple *first; + pjpidf_status *status; + pj_time_val now; + pj_parsed_time pnow; + + first = pjpidf_op.pres.get_first_tuple(pres->uas_data.pidf); + pj_assert(first); + status = pjpidf_op.tuple.get_status(first); + pj_assert(status); + pjpidf_op.status.set_basic_open(status, is_online); + + /* Update timestamp. */ + if (pres->timestamp.ptr == 0) { + pres->timestamp.ptr = pj_pool_alloc(pres->sub->pool, 24); + } + pj_gettimeofday(&now); + pj_time_decode(&now, &pnow); + pres->timestamp.slen = sprintf(pres->timestamp.ptr, + "%04d-%02d-%02dT%02d:%02d:%02dZ", + pnow.year, pnow.mon, pnow.day, + pnow.hour, pnow.min, pnow.sec); + pjpidf_op.tuple.set_timestamp_np(pres->sub->pool, first, &pres->timestamp); + + } else if (pres->pres_type == PJSIP_PRES_TYPE_XPIDF) { + pjxpidf_set_status( pres->uas_data.xpidf, is_online ); + + } else { + pj_assert(0); + } + + /* Send notify. */ + return pjsip_event_sub_notify( pres->sub, state, &reason, pres->uas_body); +} + +/* + * Destroy subscription (can be called for both subscriber and notifier). + */ +PJ_DEF(pj_status_t) pjsip_presence_destroy( pjsip_presentity *pres ) +{ + return pjsip_event_sub_destroy(pres->sub); +} + +/* + * This callback is called by event framework to query whether we want to + * accept an incoming subscription. + */ +static void on_query_subscribe(pjsip_rx_data *rdata, int *status) +{ + if (cb.accept_presence) { + (*cb.accept_presence)(rdata, status); + } +} + +/* + * This callback is called by event framework after we accept the incoming + * subscription, to notify about the new subscription instance. + */ +static void on_subscribe(pjsip_event_sub *sub, pjsip_rx_data *rdata, + pjsip_event_sub_cb **set_sub_cb, int *expires) +{ + pjsip_presentity *pres; + pjsip_accept_hdr *accept; + + pres = pj_pool_calloc(sub->pool, 1, sizeof(*pres)); + pres->sub = sub; + pres->pres_type = PJSIP_PRES_TYPE_PIDF; + sub->user_data = pres; + *set_sub_cb = &sub_cb; + + accept = pjsip_msg_find_hdr(rdata->msg, PJSIP_H_ACCEPT, NULL); + if (accept) { + unsigned i; + int found = 0; + for (i=0; icount && !found; ++i) { + int j; + for (j=0; jvalues[i], &accept_names[j])) { + pres->pres_type = j; + found = 1; + break; + } + } + } + pj_assert(found ); + } + + (*cb.on_received_request)(pres, rdata, expires); +} + +/* + * This callback is called by event framework when the subscription is + * terminated. + */ +static void on_sub_terminated(pjsip_event_sub *sub, const pj_str_t *reason) +{ + pjsip_presentity *pres = sub->user_data; + if (cb.on_terminated) + (*cb.on_terminated)(pres, reason); +} + +/* + * This callback is called by event framework when it receives incoming + * SUBSCRIBE request to refresh the subscription. + */ +static void on_sub_received_refresh(pjsip_event_sub *sub, pjsip_rx_data *rdata) +{ + pjsip_presentity *pres = sub->user_data; + if (cb.on_received_refresh) + (*cb.on_received_refresh)(pres, rdata); +} + +/* + * This callback is called by event framework when it receives incoming + * NOTIFY request. + */ +static void on_received_notify(pjsip_event_sub *sub, pjsip_rx_data *rdata) +{ + pjsip_presentity *pres = sub->user_data; + + if (cb.on_received_update) { + pj_status_t is_open; + pjsip_msg_body *body; + int i; + + body = rdata->msg->body; + if (!body) + return; + + for (i=0; icontent_type.type, &accept_types[i].type) && + !pj_stricmp(&body->content_type.subtype, &accept_types[i].subtype)) + { + break; + } + } + + if (i==PJSIP_PRES_TYPE_PIDF) { + pjpidf_pres *pres; + pjpidf_tuple *tuple; + pjpidf_status *status; + + pres = pjpidf_parse(rdata->pool, body->data, body->len); + if (!pres) + return; + tuple = pjpidf_pres_get_first_tuple(pres); + if (!tuple) + return; + status = pjpidf_tuple_get_status(tuple); + if (!status) + return; + is_open = pjpidf_status_is_basic_open(status); + + } else if (i==PJSIP_PRES_TYPE_XPIDF) { + pjxpidf_pres *pres; + + pres = pjxpidf_parse(rdata->pool, body->data, body->len); + if (!pres) + return; + is_open = pjxpidf_get_status(pres); + + } else { + return; + } + + (*cb.on_received_update)(pres, is_open); + } +} + -- cgit v1.2.3