Exemplo n.º 1
0
static void pubc_refresh_timer_cb( pj_timer_heap_t *timer_heap,
				   struct pj_timer_entry *entry)
{
    pjsip_publishc *pubc = (pjsip_publishc*) entry->user_data;
    pjsip_tx_data *tdata;
    pj_status_t status;
    
    PJ_UNUSED_ARG(timer_heap);

    entry->id = 0;
    status = pjsip_publishc_publish(pubc, 1, &tdata);
    if (status != PJ_SUCCESS) {
	char errmsg[PJ_ERR_MSG_SIZE];
	pj_str_t reason = pj_strerror(status, errmsg, sizeof(errmsg));
	call_callback(pubc, status, 400, &reason, NULL, -1);
	return;
    }

    status = pjsip_publishc_send(pubc, tdata);
    /* No need to call callback as it should have been called */
}
Exemplo n.º 2
0
/*
 * Send PUBLISH request.
 */
pj_status_t
SIPPresence::send_publish(SIPPresence * pres)
{
    pjsip_tx_data *tdata;
    pj_status_t status;

    DEBUG("Send PUBLISH (%s).", pres->getAccount()->getAccountID().c_str());

    SIPAccount * acc = pres->getAccount();
    std::string contactWithAngles =  acc->getFromUri();
    contactWithAngles.erase(contactWithAngles.find('>'));
    int semicolon = contactWithAngles.find_first_of(":");
    std::string contactWithoutAngles = contactWithAngles.substr(semicolon + 1);
//    pj_str_t contact = pj_str(strdup(contactWithoutAngles.c_str()));
//    pj_memcpy(&status_data.info[0].contact, &contt, sizeof(pj_str_t));;

    /* Create PUBLISH request */
    char *bpos;
    pj_str_t entity;

    status = pjsip_publishc_publish(pres->publish_sess_, PJ_TRUE, &tdata);
    pj_str_t from = pj_strdup3(pres->pool_, acc->getFromUri().c_str());

    if (status != PJ_SUCCESS) {
        ERROR("Error creating PUBLISH request", status);
        goto on_error;
    }

    if ((bpos = pj_strchr(&from, '<')) != NULL) {
        char *epos = pj_strchr(&from, '>');

        if (epos - bpos < 2) {
            pj_assert(!"Unexpected invalid URI");
            status = PJSIP_EINVALIDURI;
            goto on_error;
        }

        entity.ptr = bpos + 1;
        entity.slen = epos - bpos - 1;
    } else {
        entity = from;
    }

    /* Create and add PIDF message body */
    status = pjsip_pres_create_pidf(tdata->pool, pres->getStatus(),
                                    &entity, &tdata->msg->body);

    pres_msg_data msg_data;

    if (status != PJ_SUCCESS) {
        ERROR("Error creating PIDF for PUBLISH request");
        pjsip_tx_data_dec_ref(tdata);
        goto on_error;
    }

    pj_bzero(&msg_data, sizeof(msg_data));
    pj_list_init(&msg_data.hdr_list);
    pjsip_media_type_init(&msg_data.multipart_ctype, NULL, NULL);
    pj_list_init(&msg_data.multipart_parts);

    pres->fillDoc(tdata, &msg_data);

    /* Send the PUBLISH request */
    status = pjsip_publishc_send(pres->publish_sess_, tdata);

    if (status == PJ_EPENDING) {
        WARN("Previous request is in progress, ");
    } else if (status != PJ_SUCCESS) {
        ERROR("Error sending PUBLISH request");
        goto on_error;
    }

    return PJ_SUCCESS;

on_error:

    if (pres->publish_sess_) {
        pjsip_publishc_destroy(pres->publish_sess_);
        pres->publish_sess_ = NULL;
    }

    return status;
}
Exemplo n.º 3
0
static void tsx_callback(void *token, pjsip_event *event)
{
    pj_status_t status;
    pjsip_publishc *pubc = (pjsip_publishc*) token;
    pjsip_transaction *tsx = event->body.tsx_state.tsx;
    
    /* Decrement pending transaction counter. */
    pj_assert(pubc->pending_tsx > 0);
    --pubc->pending_tsx;

    /* If publication data has been deleted by user then remove publication 
     * data from transaction's callback, and don't call callback.
     */
    if (pubc->_delete_flag) {

	/* Nothing to do */
	;

    } else if (tsx->status_code == PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED ||
	       tsx->status_code == PJSIP_SC_UNAUTHORIZED)
    {
	pjsip_rx_data *rdata = event->body.tsx_state.src.rdata;
	pjsip_tx_data *tdata;

	status = pjsip_auth_clt_reinit_req( &pubc->auth_sess,
					    rdata, 
					    tsx->last_tx,  
					    &tdata);
	if (status != PJ_SUCCESS) {
	    call_callback(pubc, status, tsx->status_code, 
			  &rdata->msg_info.msg->line.status.reason,
			  rdata, -1);
	} else {
    	    status = pjsip_publishc_send(pubc, tdata);
	}

    } else {
	pjsip_rx_data *rdata;
	pj_int32_t expiration = 0xFFFF;

	if (tsx->status_code/100 == 2) {
	    pjsip_msg *msg;
	    pjsip_expires_hdr *expires;
	    pjsip_generic_string_hdr *etag_hdr;
	    const pj_str_t STR_ETAG = { "SIP-ETag", 8 };

	    rdata = event->body.tsx_state.src.rdata;
	    msg = rdata->msg_info.msg;

	    /* Save ETag value */
	    etag_hdr = (pjsip_generic_string_hdr*)
		       pjsip_msg_find_hdr_by_name(msg, &STR_ETAG, NULL);
	    if (etag_hdr) {
		pj_strdup(pubc->pool, &pubc->etag, &etag_hdr->hvalue);
	    } else {
		pubc->etag.slen = 0;
	    }

	    /* Update expires value */
	    expires = (pjsip_expires_hdr*)
	    	      pjsip_msg_find_hdr(msg, PJSIP_H_EXPIRES, NULL);

	    if (expires)
		expiration = expires->ivalue;
	    
	    if (pubc->auto_refresh && expiration!=0 && expiration!=0xFFFF) {
		pj_time_val delay = { 0, 0};

		delay.sec = expiration - DELAY_BEFORE_REFRESH;
		if (pubc->expires != PJSIP_PUBC_EXPIRATION_NOT_SPECIFIED && 
		    delay.sec > (pj_int32_t)pubc->expires) 
		{
		    delay.sec = pubc->expires;
		}
		if (delay.sec < DELAY_BEFORE_REFRESH) 
		    delay.sec = DELAY_BEFORE_REFRESH;
		pubc->timer.cb = &pubc_refresh_timer_cb;
		pubc->timer.id = REFRESH_TIMER;
		pubc->timer.user_data = pubc;
		pjsip_endpt_schedule_timer( pubc->endpt, &pubc->timer, &delay);
		pj_gettimeofday(&pubc->last_refresh);
		pubc->next_refresh = pubc->last_refresh;
		pubc->next_refresh.sec += delay.sec;
	    }

	} else {
	    rdata = (event->body.tsx_state.type==PJSIP_EVENT_RX_MSG) ? 
			event->body.tsx_state.src.rdata : NULL;
	}


	/* Call callback. */
	if (expiration == 0xFFFF) expiration = -1;

	/* Temporarily increment pending_tsx to prevent callback from
	 * destroying pubc.
	 */
	++pubc->pending_tsx;

	call_callback(pubc, PJ_SUCCESS, tsx->status_code, 
		      (rdata ? &rdata->msg_info.msg->line.status.reason 
			: pjsip_get_status_text(tsx->status_code)),
		      rdata, expiration);

	--pubc->pending_tsx;
    }

    /* Delete the record if user destroy pubc during the callback. */
    if (pubc->_delete_flag && pubc->pending_tsx==0) {
	pjsip_publishc_destroy(pubc);
    }
}
Exemplo n.º 4
0
/*
 * 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) {
	char *bpos;
	pj_str_t entity;

	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;
	pres_status.info[0].id = acc->cfg.pidf_tuple_id;
	/* .. including RPID information */
	pj_memcpy(&pres_status.info[0].rpid, &acc->rpid, 
		  sizeof(pjrpid_element));

	/* Be careful not to send PIDF with presence entity ID containing
	 * "<" character.
	 */
	if ((bpos=pj_strchr(&acc_cfg->id, '<')) != NULL) {
	    char *epos = pj_strchr(&acc_cfg->id, '>');
	    if (epos - bpos < 2) {
		pj_assert(!"Unexpected invalid URI");
		status = PJSIP_EINVALIDURI;
		goto on_error;
	    }
	    entity.ptr = bpos+1;
	    entity.slen = epos - bpos - 1;
	} else {
	    entity = acc_cfg->id;
	}

	/* Create and add PIDF message body */
	status = pjsip_pres_create_pidf(tdata->pool, &pres_status,
					&entity, &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:
    if (acc->publish_sess) {
	pjsip_publishc_destroy(acc->publish_sess);
	acc->publish_sess = NULL;
    }
    return status;
}
Exemplo n.º 5
0
static void tsx_callback(void *token, pjsip_event *event)
{
    pj_status_t status;
    pjsip_publishc *pubc = (pjsip_publishc*) token;
    pjsip_transaction *tsx = event->body.tsx_state.tsx;
    
    /* Decrement pending transaction counter. */
    pj_assert(pubc->pending_tsx > 0);
    --pubc->pending_tsx;

    /* Mark that we're in callback to prevent deletion (#1164) */
    ++pubc->in_callback;

    /* If publication data has been deleted by user then remove publication 
     * data from transaction's callback, and don't call callback.
     */
    if (pubc->_delete_flag) {

	/* Nothing to do */
	;

    } else if (tsx->status_code == PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED ||
	       tsx->status_code == PJSIP_SC_UNAUTHORIZED)
    {
	pjsip_rx_data *rdata = event->body.tsx_state.src.rdata;
	pjsip_tx_data *tdata;

	status = pjsip_auth_clt_reinit_req( &pubc->auth_sess,
					    rdata, 
					    tsx->last_tx,  
					    &tdata);
	if (status != PJ_SUCCESS) {
	    call_callback(pubc, status, tsx->status_code, 
			  &rdata->msg_info.msg->line.status.reason,
			  rdata, -1);
	} else {
    	    status = pjsip_publishc_send(pubc, tdata);
	}

    } else {
	pjsip_rx_data *rdata;
	pj_int32_t expiration = 0xFFFF;

	if (tsx->status_code/100 == 2) {
	    pjsip_msg *msg;
	    pjsip_expires_hdr *expires;
	    pjsip_generic_string_hdr *etag_hdr;
	    const pj_str_t STR_ETAG = { "SIP-ETag", 8 };

	    rdata = event->body.tsx_state.src.rdata;
	    msg = rdata->msg_info.msg;

	    /* Save ETag value */
	    etag_hdr = (pjsip_generic_string_hdr*)
		       pjsip_msg_find_hdr_by_name(msg, &STR_ETAG, NULL);
	    if (etag_hdr) {
		pj_strdup(pubc->pool, &pubc->etag, &etag_hdr->hvalue);
	    } else {
		pubc->etag.slen = 0;
	    }

	    /* Update expires value */
	    expires = (pjsip_expires_hdr*)
	    	      pjsip_msg_find_hdr(msg, PJSIP_H_EXPIRES, NULL);

	    if (pubc->auto_refresh && expires)
		expiration = expires->ivalue;
	    
	    if (pubc->auto_refresh && expiration!=0 && expiration!=0xFFFF) {
		pj_time_val delay = { 0, 0};

		/* Cancel existing timer, if any */
		if (pubc->timer.id != 0) {
		    pjsip_endpt_cancel_timer(pubc->endpt, &pubc->timer);
		    pubc->timer.id = 0;
		}

		delay.sec = expiration - DELAY_BEFORE_REFRESH;
		if (pubc->expires != PJSIP_PUBC_EXPIRATION_NOT_SPECIFIED && 
		    delay.sec > (pj_int32_t)pubc->expires) 
		{
		    delay.sec = pubc->expires;
		}
		if (delay.sec < DELAY_BEFORE_REFRESH) 
		    delay.sec = DELAY_BEFORE_REFRESH;
		pubc->timer.cb = &pubc_refresh_timer_cb;
		pubc->timer.id = REFRESH_TIMER;
		pubc->timer.user_data = pubc;
		pjsip_endpt_schedule_timer( pubc->endpt, &pubc->timer, &delay);
		pj_gettimeofday(&pubc->last_refresh);
		pubc->next_refresh = pubc->last_refresh;
		pubc->next_refresh.sec += delay.sec;
	    }

	} else {
	    rdata = (event->body.tsx_state.type==PJSIP_EVENT_RX_MSG) ? 
			event->body.tsx_state.src.rdata : NULL;
	}


	/* Call callback. */
	if (expiration == 0xFFFF) expiration = -1;

	/* Temporarily increment pending_tsx to prevent callback from
	 * destroying pubc.
	 */
	++pubc->pending_tsx;

	call_callback(pubc, PJ_SUCCESS, tsx->status_code, 
		      (rdata ? &rdata->msg_info.msg->line.status.reason 
			: pjsip_get_status_text(tsx->status_code)),
		      rdata, expiration);

	--pubc->pending_tsx;

	/* If we have pending request(s), send them now */
	pj_mutex_lock(pubc->mutex);
	while (!pj_list_empty(&pubc->pending_reqs)) {
	    pjsip_tx_data *tdata = pubc->pending_reqs.next;
	    pj_list_erase(tdata);

	    /* Add SIP-If-Match if we have etag and the request doesn't have
	     * one (http://trac.pjsip.org/repos/ticket/996)
	     */
	    if (pubc->etag.slen) {
		const pj_str_t STR_HNAME = { "SIP-If-Match", 12 };
		pjsip_generic_string_hdr *sim_hdr;

		sim_hdr = (pjsip_generic_string_hdr*)
			  pjsip_msg_find_hdr_by_name(tdata->msg, &STR_HNAME, NULL);
		if (!sim_hdr) {
		    /* Create the header */
		    sim_hdr = pjsip_generic_string_hdr_create(tdata->pool,
							      &STR_HNAME,
							      &pubc->etag);
		    pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)sim_hdr);

		} else {
		    /* Update */
		    if (pj_strcmp(&pubc->etag, &sim_hdr->hvalue))
			pj_strdup(tdata->pool, &sim_hdr->hvalue, &pubc->etag);
		}
	    }

	    status = pjsip_publishc_send(pubc, tdata);
	    if (status == PJ_EPENDING) {
		pj_assert(!"Not expected");
		pj_list_erase(tdata);
		pjsip_tx_data_dec_ref(tdata);
	    } else if (status == PJ_SUCCESS) {
		break;
	    }
	}
	pj_mutex_unlock(pubc->mutex);
    }

    /* No longer in callback. */
    --pubc->in_callback;

    /* Delete the record if user destroy pubc during the callback. */
    if (pubc->_delete_flag && pubc->pending_tsx==0) {
	pjsip_publishc_destroy(pubc);
    }
}