コード例 #1
0
/*
 * Client presence publication callback.
 */
void
SIPPresence::publish_cb(struct pjsip_publishc_cbparam *param)
{
    SIPPresence *pres = (SIPPresence*) param->token;

    if (param->code / 100 != 2 || param->status != PJ_SUCCESS) {

        pjsip_publishc_destroy(param->pubc);
        pres->publish_sess_ = NULL;
        std::ostringstream os;
        os << param->code;
        const std::string error = os.str() + " / "+ std::string(param->reason.ptr, param->reason.slen);

        if (param->status != PJ_SUCCESS) {
            char errmsg[PJ_ERR_MSG_SIZE];
            pj_strerror(param->status, errmsg, sizeof(errmsg));
            ERROR("Client (PUBLISH) failed, status=%d, msg=%s", param->status, errmsg);
            Manager::instance().getClient()->getPresenceManager()->serverError(
                    pres->getAccount()->getAccountID(),
                    error,
                    errmsg);

        } else if (param->code == 412) {
            /* 412 (Conditional Request Failed)
             * The PUBLISH refresh has failed, retry with new one.
             */
            WARN("Publish retry.");
            publish(pres);
        } else if ((param->code == PJSIP_SC_BAD_EVENT) || (param->code == PJSIP_SC_NOT_IMPLEMENTED)){ //489 or 501
            WARN("Client (PUBLISH) failed (%s)",error.c_str());

            Manager::instance().getClient()->getPresenceManager()->serverError(
                    pres->getAccount()->getAccountID(),
                    error,
                    "Publish not supported.");

            pres->getAccount()->supportPresence(PRESENCE_FUNCTION_PUBLISH, false);
        }

    } else {
        if (param->expiration < 1) {
            /* Could happen if server "forgot" to include Expires header
             * in the response. We will not renew, so destroy the pubc.
             */
            pjsip_publishc_destroy(param->pubc);
            pres->publish_sess_ = NULL;
        }

        pres->getAccount()->supportPresence(PRESENCE_FUNCTION_PUBLISH, true);
    }
}
コード例 #2
0
ファイル: pjsua_pres.c プロジェクト: Jopie64/pjsip
/*
 * Client presence publication callback.
 */
static void publish_cb(struct pjsip_publishc_cbparam *param)
{
    pjsua_acc *acc = (pjsua_acc*) param->token;

    if (param->code/100 != 2 || param->status != PJ_SUCCESS) {

	pjsip_publishc_destroy(param->pubc);
	acc->publish_sess = NULL;

	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 if (param->code == 412) {
	    /* 412 (Conditional Request Failed)
	     * The PUBLISH refresh has failed, retry with new one.
	     */
	    pjsua_pres_init_publish_acc(acc->index);
	    
	} else {
	    PJ_LOG(1,(THIS_FILE, 
		      "Client publication (PUBLISH) failed (%d/%.*s)",
		       param->code, (int)param->reason.slen,
		       param->reason.ptr));
	}

    } else {
	if (param->expiration == -1) {
	    /* Could happen if server "forgot" to include Expires header
	     * in the response. We will not renew, so destroy the pubc.
	     */
	    pjsip_publishc_destroy(param->pubc);
	    acc->publish_sess = NULL;
	}
    }
}
コード例 #3
0
ファイル: pjsua_pres.c プロジェクト: svn2github/pjproject
/* 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;

    /* Notify all subscribers that we're no longer available */
    while (uapres != &acc->pres_srv_list) {
	
	pjsip_pres_status pres_status;
	pj_str_t reason = { "noresource", 10 };
	pjsua_srv_pres *next;
	pjsip_tx_data *tdata;

	next = uapres->next;

	pjsip_pres_get_status(uapres->sub, &pres_status);
	
	pres_status.info[0].basic_open = pjsua_var.acc[acc_id].online_status;
	pjsip_pres_set_status(uapres->sub, &pres_status);

	if (pjsip_pres_notify(uapres->sub, 
			      PJSIP_EVSUB_STATE_TERMINATED, NULL,
			      &reason, &tdata)==PJ_SUCCESS)
	{
	    pjsip_pres_send_request(uapres->sub, tdata);
	}

	uapres = next;
    }

    /* Clear server presence subscription list because account might be reused
     * later. */
    pj_list_init(&acc->pres_srv_list);

    /* Terminate presence publication, if any */
    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;
    }
}
コード例 #4
0
ファイル: pjsua_pres.c プロジェクト: svn2github/pjproject
/*
 * Client presence publication callback.
 */
static void publish_cb(struct pjsip_publishc_cbparam *param)
{
    pjsua_acc *acc = (pjsua_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;
    }
}
コード例 #5
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;
}
コード例 #6
0
ファイル: publishc.c プロジェクト: svn2github/pjproject
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);
    }
}
コード例 #7
0
ファイル: pjsua_pres.c プロジェクト: svn2github/pjproject
/*
 * 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;
}
コード例 #8
0
ファイル: publishc.c プロジェクト: CryptoCall/pjsip
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);
    }
}