static pj_bool_t authenticate(pjsip_rx_data *rdata)
{
	RAII_VAR(struct ast_sip_endpoint *, endpoint, ast_pjsip_rdata_get_endpoint(rdata), ao2_cleanup);
	int is_ack = rdata->msg_info.msg->line.req.method.id == PJSIP_ACK_METHOD;

	ast_assert(endpoint != NULL);

	if (is_ack) {
		return PJ_FALSE;
	}

	if (ast_sip_requires_authentication(endpoint, rdata)) {
		pjsip_tx_data *tdata;
		struct unidentified_request *unid;

		pjsip_endpt_create_response(ast_sip_get_pjsip_endpoint(), rdata, 401, NULL, &tdata);
		switch (ast_sip_check_authentication(endpoint, rdata, tdata)) {
		case AST_SIP_AUTHENTICATION_CHALLENGE:
			/* Send the 401 we created for them */
			ast_sip_report_auth_challenge_sent(endpoint, rdata, tdata);
			if (pjsip_endpt_send_response2(ast_sip_get_pjsip_endpoint(), rdata, tdata, NULL, NULL) != PJ_SUCCESS) {
				pjsip_tx_data_dec_ref(tdata);
			}
			return PJ_TRUE;
		case AST_SIP_AUTHENTICATION_SUCCESS:
			/* See note in endpoint_lookup about not holding an unnecessary write lock */
			unid = ao2_find(unidentified_requests, rdata->pkt_info.src_name, OBJ_SEARCH_KEY);
			if (unid) {
				ao2_unlink(unidentified_requests, unid);
				ao2_ref(unid, -1);
			}
			ast_sip_report_auth_success(endpoint, rdata);
			break;
		case AST_SIP_AUTHENTICATION_FAILED:
			log_failed_request(rdata, "Failed to authenticate", 0, 0);
			ast_sip_report_auth_failed_challenge_response(endpoint, rdata);
			if (pjsip_endpt_send_response2(ast_sip_get_pjsip_endpoint(), rdata, tdata, NULL, NULL) != PJ_SUCCESS) {
				pjsip_tx_data_dec_ref(tdata);
			}
			return PJ_TRUE;
		case AST_SIP_AUTHENTICATION_ERROR:
			log_failed_request(rdata, "Error to authenticate", 0, 0);
			ast_sip_report_auth_failed_challenge_response(endpoint, rdata);
			pjsip_tx_data_dec_ref(tdata);
			pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
			return PJ_TRUE;
		}
		pjsip_tx_data_dec_ref(tdata);
	} else if (endpoint == artificial_endpoint) {
		/* Uh. Oh.  The artificial endpoint couldn't challenge so block the request. */
		pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
		return PJ_TRUE;
	}

	return PJ_FALSE;
}
static pj_bool_t mod_stateless_on_rx_request(pjsip_rx_data *rdata)
{
    const pj_str_t stateless_user = { "0", 1 };
    pjsip_uri *uri;
    pjsip_sip_uri *sip_uri;

    uri = pjsip_uri_get_uri(rdata->msg_info.msg->line.req.uri);

    /* Only want to receive SIP/SIPS scheme */
    if (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))
	return PJ_FALSE;

    sip_uri = (pjsip_sip_uri*) uri;

    /* Check for matching user part */
    if (pj_strcmp(&sip_uri->user, &stateless_user)!=0)
	return PJ_FALSE;

    /*
     * Yes, this is for us.
     */

    /* Ignore ACK request */
    if (rdata->msg_info.msg->line.req.method.id == PJSIP_ACK_METHOD)
	return PJ_TRUE;

    /*
     * Respond statelessly with 200/OK.
     */
    pjsip_endpt_respond_stateless(app.sip_endpt, rdata, 200, NULL,
				  NULL, NULL);
    app.server.cur_state.stateless_cnt++;
    return PJ_TRUE;
}
Exemple #3
0
/* Callback to handle incoming requests. */
static pj_bool_t on_rx_request( pjsip_rx_data *rdata )
{
    /* Respond (statelessly) all incoming requests (except ACK!) 
     * with 501 (Not Implemented)
     */
    if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) {
	pjsip_endpt_respond_stateless( sip_endpt, rdata, 
				       code, NULL,
				       &hdr_list, NULL);
    }
    return PJ_TRUE;
}
/* Callback to be called to handle incoming requests. */
static pj_bool_t on_rx_request( pjsip_rx_data *rdata )
{
    pjsip_tx_data *tdata;
    pj_status_t status;


    /* Verify incoming request */
    status = proxy_verify_request(rdata);
    if (status != PJ_SUCCESS) {
	app_perror("RX invalid request", status);
	return PJ_TRUE;
    }

    /*
     * Request looks sane, next clone the request to create transmit data.
     */
    status = pjsip_endpt_create_request_fwd(global.endpt, rdata, NULL,
					    NULL, 0, &tdata);
    if (status != PJ_SUCCESS) {
	pjsip_endpt_respond_stateless(global.endpt, rdata,
				      PJSIP_SC_INTERNAL_SERVER_ERROR, NULL, 
				      NULL, NULL);
	return PJ_TRUE;
    }


    /* Process routing */
    status = proxy_process_routing(tdata);
    if (status != PJ_SUCCESS) {
	app_perror("Error processing route", status);
	return PJ_TRUE;
    }

    /* Calculate target */
    status = proxy_calculate_target(rdata, tdata);
    if (status != PJ_SUCCESS) {
	app_perror("Error calculating target", status);
	return PJ_TRUE;
    }

    /* Target is set, forward the request */
    status = pjsip_endpt_send_request_stateless(global.endpt, tdata, 
						NULL, NULL);
    if (status != PJ_SUCCESS) {
	app_perror("Error forwarding request", status);
	return PJ_TRUE;
    }

    return PJ_TRUE;
}
static pj_bool_t mod_responder_on_rx_request(pjsip_rx_data *rdata)
{
    const pj_str_t reason = pj_str("Not expecting request at this URI");

    /*
     * Respond any requests (except ACK!) with 500.
     */
    if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) {
	pjsip_endpt_respond_stateless(app.sip_endpt, rdata, 500, &reason,
				      NULL, NULL);
    }

    return PJ_TRUE;
}
Exemple #6
0
/* Calculate new target for the request */
static pj_status_t proxy_calculate_target(pjsip_rx_data *rdata,
        pjsip_tx_data *tdata)
{
    pjsip_sip_uri *target;

    /* RFC 3261 Section 16.5 Determining Request Targets */

    target = (pjsip_sip_uri*) tdata->msg->line.req.uri;

    /* If the Request-URI of the request contains an maddr parameter, the
     * Request-URI MUST be placed into the target set as the only target
     * URI, and the proxy MUST proceed to Section 16.6.
     */
    if (target->maddr_param.slen) {
        proxy_postprocess(tdata);
        return PJ_SUCCESS;
    }


    /* If the domain of the Request-URI indicates a domain this element is
     * not responsible for, the Request-URI MUST be placed into the target
     * set as the only target, and the element MUST proceed to the task of
     * Request Forwarding (Section 16.6).
     */
    if (!is_uri_local(target)) {
        proxy_postprocess(tdata);
        return PJ_SUCCESS;
    }

    /* If the target set for the request has not been predetermined as
     * described above, this implies that the element is responsible for the
     * domain in the Request-URI, and the element MAY use whatever mechanism
     * it desires to determine where to send the request.
     */

    /* We're not interested to receive request destined to us, so
     * respond with 404/Not Found (only if request is not ACK!).
     */
    if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) {
        pjsip_endpt_respond_stateless(global.endpt, rdata,
                                      PJSIP_SC_NOT_FOUND, NULL,
                                      NULL, NULL);
    }

    /* Delete the request since we're not forwarding it */
    pjsip_tx_data_dec_ref(tdata);

    return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_NOT_FOUND);
}
Exemple #7
0
void UE::on_rx_request(pjsip_rx_data *rdata)
{
 pjsip_msg* msg = rdata->msg_info.msg;

  pj_str_t message;
  stra(&message, "MESSAGE");
  pjsip_method msg_method;
  pjsip_method_init(&msg_method, _pool, &message);
  if (pjsip_method_cmp(&msg_method, &msg->line.req.method) == 0)
  {
    std::string body((char*)msg->body->data, msg->body->len);
    pjsip_transaction* tsx;
    pjsip_endpt_respond(get_global_endpoint(), NULL, rdata, 200, NULL, NULL, NULL, &tsx);
  } else {
    pjsip_endpt_respond_stateless(get_global_endpoint(), rdata, 
        500, NULL,
        NULL, NULL);
  }
}
Exemple #8
0
static pj_bool_t acl_on_rx_msg(pjsip_rx_data *rdata)
{
	RAII_VAR(struct ao2_container *, acls, ast_sorcery_retrieve_by_fields(
			 ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE,
			 AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL), ao2_cleanup);
	RAII_VAR(struct ast_sip_acl *, matched_acl, NULL, ao2_cleanup);

	if (!acls) {
		ast_log(LOG_ERROR, "Unable to retrieve ACL sorcery data\n");
		return PJ_FALSE;
	}

	if ((matched_acl = ao2_callback(acls, 0, check_acls, rdata))) {
		if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) {
			pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 403, NULL, NULL, NULL);
		}
		return PJ_TRUE;
	}

	return PJ_FALSE;
}
//////////////////////////////////////////////////////////////////////////
// Request handler to receive out-of-dialog NOTIFY (from Asterisk)
static pj_bool_t on_rx_request(pjsip_rx_data *rdata)
{
	if (strstr(pj_strbuf(&rdata->msg_info.msg->line.req.method.name),
		"NOTIFY"))
	{
		pjsip_generic_string_hdr * hdr;
		pj_str_t did_str = pj_str("Event");
		hdr = (pjsip_generic_string_hdr*) pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &did_str, NULL);
		if (!hdr) return false;

		// We have an event header, now determine if it's contents are "message-summary"
		if (pj_strcmp2(&hdr->hvalue, "message-summary")) return false;

		pjsip_msg_body * body_p = rdata->msg_info.msg->body;

		wchar_t* buf = (wchar_t*)pj_pool_alloc(app_config.pool, body_p->len);
		buf = PJ_STRING_TO_NATIVE((char*)body_p->data, buf, body_p->len);

		// Process body message as desired...
		if (strncmp((char*)body_p->data, "Messages-Waiting: yes", body_p->len) != 0)
		{
			if (cb_mwi != 0) cb_mwi(1, buf);
		}
		else
		{
			if (cb_mwi != 0) cb_mwi(0, buf);
		}
		PJ_LOG(3,(THIS_FILE,"MWI message: %s", buf));
	}

	pjsip_endpt_respond_stateless(pjsip_ua_get_endpt(pjsip_ua_instance()),
		rdata, 200, NULL,
		NULL, NULL);

	return PJ_TRUE;
}
Exemple #10
0
static pj_bool_t on_rx_request( pjsip_rx_data *rdata )
{
    pj_sockaddr hostaddr;
    char temp[80], hostip[PJ_INET6_ADDRSTRLEN];
    pj_str_t local_uri;
    pjsip_dialog *dlg;
    pjsip_rdata_sdp_info *sdp_info;
    pjmedia_sdp_session *answer = NULL;
    pjsip_tx_data *tdata = NULL;
    call_t *call = NULL;
    unsigned i;
    pj_status_t status;

    PJ_LOG(3,(THIS_FILE, "RX %.*s from %s",
	      (int)rdata->msg_info.msg->line.req.method.name.slen,
	      rdata->msg_info.msg->line.req.method.name.ptr,
	      rdata->pkt_info.src_name));

    if (rdata->msg_info.msg->line.req.method.id == PJSIP_REGISTER_METHOD) {
	/* Let me be a registrar! */
	pjsip_hdr hdr_list, *h;
	pjsip_msg *msg;
	int expires = -1;

	pj_list_init(&hdr_list);
	msg = rdata->msg_info.msg;
	h = (pjsip_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_EXPIRES, NULL);
	if (h) {
	    expires = ((pjsip_expires_hdr*)h)->ivalue;
	    pj_list_push_back(&hdr_list, pjsip_hdr_clone(rdata->tp_info.pool, h));
	    PJ_LOG(3,(THIS_FILE, " Expires=%d", expires));
	}
	if (expires != 0) {
	    h = (pjsip_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_CONTACT, NULL);
	    if (h)
		pj_list_push_back(&hdr_list, pjsip_hdr_clone(rdata->tp_info.pool, h));
	}

	pjsip_endpt_respond(app.sip_endpt, &mod_sipecho, rdata, 200, NULL,
	                    &hdr_list, NULL, NULL);
	return PJ_TRUE;
    }

    if (rdata->msg_info.msg->line.req.method.id != PJSIP_INVITE_METHOD) {
	if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) {
	    pj_str_t reason = pj_str("Go away");
	    pjsip_endpt_respond_stateless( app.sip_endpt, rdata,
					   400, &reason,
					   NULL, NULL);
	}
	return PJ_TRUE;
    }

    sdp_info = pjsip_rdata_get_sdp_info(rdata);
    if (!sdp_info || !sdp_info->sdp) {
	pj_str_t reason = pj_str("Require valid offer");
	pjsip_endpt_respond_stateless( app.sip_endpt, rdata,
				       400, &reason,
				       NULL, NULL);
    }

    for (i=0; i<MAX_CALLS; ++i) {
	if (app.call[i].inv == NULL) {
	    call = &app.call[i];
	    break;
	}
    }

    if (i==MAX_CALLS) {
	pj_str_t reason = pj_str("We're full");
	pjsip_endpt_respond_stateless( app.sip_endpt, rdata,
				       PJSIP_SC_BUSY_HERE, &reason,
				       NULL, NULL);
	return PJ_TRUE;
    }

    /* Generate Contact URI */
    status = pj_gethostip(AF, &hostaddr);
    if (status != PJ_SUCCESS) {
	app_perror(THIS_FILE, "Unable to retrieve local host IP", status);
	return PJ_TRUE;
    }
    pj_sockaddr_print(&hostaddr, hostip, sizeof(hostip), 2);
    pj_ansi_sprintf(temp, "<sip:sipecho@%s:%d>", hostip, SIP_PORT);
    local_uri = pj_str(temp);

    status = pjsip_dlg_create_uas( pjsip_ua_instance(), rdata,
				   &local_uri, &dlg);

    if (status == PJ_SUCCESS)
	answer = create_answer(call-app.call, dlg->pool, sdp_info->sdp);
    if (status == PJ_SUCCESS)
    	status = pjsip_inv_create_uas( dlg, rdata, answer, 0, &call->inv);
    if (status == PJ_SUCCESS)
    	status = pjsip_inv_initial_answer(call->inv, rdata, 100,
				          NULL, NULL, &tdata);
    if (status == PJ_SUCCESS)
    	status = pjsip_inv_send_msg(call->inv, tdata);

    if (status == PJ_SUCCESS)
    	status = pjsip_inv_answer(call->inv, 180, NULL,
    	                          NULL, &tdata);
    if (status == PJ_SUCCESS)
    	status = pjsip_inv_send_msg(call->inv, tdata);

    if (status == PJ_SUCCESS)
    	status = pjsip_inv_answer(call->inv, 200, NULL,
    	                          NULL, &tdata);
    if (status == PJ_SUCCESS)
    	status = pjsip_inv_send_msg(call->inv, tdata);

    if (status != PJ_SUCCESS) {
	pjsip_endpt_respond_stateless( app.sip_endpt, rdata,
				       500, NULL, NULL, NULL);
	destroy_call(call);
    } else {
	call->inv->mod_data[mod_sipecho.id] = call;
    }

    return PJ_TRUE;
}
static struct ast_sip_aor *find_registrar_aor(struct pjsip_rx_data *rdata, struct ast_sip_endpoint *endpoint)
{
	struct ast_sip_aor *aor = NULL;
	char *aor_name = NULL;
	char *domain_name;
	char *username = NULL;
	int i;

	for (i = 0; i < AST_VECTOR_SIZE(&endpoint->ident_method_order); ++i) {
		pjsip_sip_uri *uri;
		pjsip_authorization_hdr *header = NULL;

		switch (AST_VECTOR_GET(&endpoint->ident_method_order, i)) {
		case AST_SIP_ENDPOINT_IDENTIFY_BY_USERNAME:
			uri = pjsip_uri_get_uri(rdata->msg_info.to->uri);

			domain_name = ast_alloca(uri->host.slen + 1);
			ast_copy_pj_str(domain_name, &uri->host, uri->host.slen + 1);
			username = ast_alloca(uri->user.slen + 1);
			ast_copy_pj_str(username, &uri->user, uri->user.slen + 1);

			/*
			 * We may want to match without any user options getting
			 * in the way.
			 */
			AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(username);

			aor_name = find_aor_name(username, domain_name, endpoint->aors);
			if (aor_name) {
				ast_debug(3, "Matched aor '%s' by To username\n", aor_name);
			}
			break;
		case AST_SIP_ENDPOINT_IDENTIFY_BY_AUTH_USERNAME:
			while ((header = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_AUTHORIZATION,
				header ? header->next : NULL))) {
				if (header && !pj_stricmp2(&header->scheme, "digest")) {
					username = ast_alloca(header->credential.digest.username.slen + 1);
					ast_copy_pj_str(username, &header->credential.digest.username, header->credential.digest.username.slen + 1);
					domain_name = ast_alloca(header->credential.digest.realm.slen + 1);
					ast_copy_pj_str(domain_name, &header->credential.digest.realm, header->credential.digest.realm.slen + 1);

					aor_name = find_aor_name(username, domain_name, endpoint->aors);
					if (aor_name) {
						ast_debug(3, "Matched aor '%s' by Authentication username\n", aor_name);
						break;
					}
				}
			}
			break;
		default:
			continue;
		}

		if (aor_name) {
			break;
		}
	}

	if (ast_strlen_zero(aor_name) || !(aor = ast_sip_location_retrieve_aor(aor_name))) {
		/* The provided AOR name was not found (be it within the configuration or sorcery itself) */
		pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 404, NULL, NULL, NULL);
		ast_sip_report_req_no_support(endpoint, rdata, "registrar_requested_aor_not_found");
		ast_log(LOG_WARNING, "AOR '%s' not found for endpoint '%s'\n",
			username ?: "", ast_sorcery_object_get_id(endpoint));
	}
static int register_aor_core(pjsip_rx_data *rdata,
	struct ast_sip_endpoint *endpoint,
	struct ast_sip_aor *aor,
	const char *aor_name,
	struct ao2_container *contacts)
{
	static const pj_str_t USER_AGENT = { "User-Agent", 10 };

	int added = 0, updated = 0, deleted = 0;
	pjsip_contact_hdr *contact_hdr = NULL;
	struct registrar_contact_details details = { 0, };
	pjsip_tx_data *tdata;
	RAII_VAR(struct ast_str *, path_str, NULL, ast_free);
	struct ast_sip_contact *response_contact;
	char *user_agent = NULL;
	pjsip_user_agent_hdr *user_agent_hdr;
	pjsip_expires_hdr *expires_hdr;
	pjsip_via_hdr *via_hdr;
	pjsip_via_hdr *via_hdr_last;
	char *via_addr = NULL;
	int via_port = 0;
	pjsip_cid_hdr *call_id_hdr;
	char *call_id = NULL;
	size_t alloc_size;

	/* So we don't count static contacts against max_contacts we prune them out from the container */
	ao2_callback(contacts, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, registrar_prune_static, NULL);

	if (registrar_validate_contacts(rdata, contacts, aor, &added, &updated, &deleted)) {
		/* The provided Contact headers do not conform to the specification */
		pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 400, NULL, NULL, NULL);
		ast_sip_report_failed_acl(endpoint, rdata, "registrar_invalid_contacts_provided");
		ast_log(LOG_WARNING, "Failed to validate contacts in REGISTER request from '%s'\n",
				ast_sorcery_object_get_id(endpoint));
		return PJ_TRUE;
	}

	if (registrar_validate_path(rdata, aor, &path_str)) {
		/* Ensure that intervening proxies did not make invalid modifications to the request */
		pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 420, NULL, NULL, NULL);
		ast_log(LOG_WARNING, "Invalid modifications made to REGISTER request from '%s' by intervening proxy\n",
				ast_sorcery_object_get_id(endpoint));
		return PJ_TRUE;
	}

	if ((MAX(added - deleted, 0) + (!aor->remove_existing ? ao2_container_count(contacts) : 0)) > aor->max_contacts) {
		/* Enforce the maximum number of contacts */
		pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 403, NULL, NULL, NULL);
		ast_sip_report_failed_acl(endpoint, rdata, "registrar_attempt_exceeds_maximum_configured_contacts");
		ast_log(LOG_WARNING, "Registration attempt from endpoint '%s' to AOR '%s' will exceed max contacts of %u\n",
				ast_sorcery_object_get_id(endpoint), aor_name, aor->max_contacts);
		return PJ_TRUE;
	}

	if (!(details.pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "Contact Comparison", 256, 256))) {
		pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
		return PJ_TRUE;
	}

	user_agent_hdr = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &USER_AGENT, NULL);
	if (user_agent_hdr) {
		alloc_size = pj_strlen(&user_agent_hdr->hvalue) + 1;
		user_agent = ast_alloca(alloc_size);
		ast_copy_pj_str(user_agent, &user_agent_hdr->hvalue, alloc_size);
	}

	/* Find the first Via header */
	via_hdr = via_hdr_last = (pjsip_via_hdr*) pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_VIA, NULL);
	if (via_hdr) {
		/* Find the last Via header */
		while ( (via_hdr = (pjsip_via_hdr*) pjsip_msg_find_hdr(rdata->msg_info.msg,
				PJSIP_H_VIA, via_hdr->next)) != NULL) {
			via_hdr_last = via_hdr;
		}
		alloc_size = pj_strlen(&via_hdr_last->sent_by.host) + 1;
		via_addr = ast_alloca(alloc_size);
		ast_copy_pj_str(via_addr, &via_hdr_last->sent_by.host, alloc_size);
		via_port=via_hdr_last->sent_by.port;
	}

	call_id_hdr = (pjsip_cid_hdr*) pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CALL_ID, NULL);
	if (call_id_hdr) {
		alloc_size = pj_strlen(&call_id_hdr->id) + 1;
		call_id = ast_alloca(alloc_size);
		ast_copy_pj_str(call_id, &call_id_hdr->id, alloc_size);
	}

	/* Iterate each provided Contact header and add, update, or delete */
	while ((contact_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, contact_hdr ? contact_hdr->next : NULL))) {
		int expiration;
		char contact_uri[pjsip_max_url_size];
		RAII_VAR(struct ast_sip_contact *, contact, NULL, ao2_cleanup);

		if (contact_hdr->star) {
			/* A star means to unregister everything, so do so for the possible contacts */
			ao2_callback(contacts, OBJ_NODATA | OBJ_MULTIPLE, registrar_delete_contact, (void *)aor_name);
			break;
		}

		if (!PJSIP_URI_SCHEME_IS_SIP(contact_hdr->uri) && !PJSIP_URI_SCHEME_IS_SIPS(contact_hdr->uri)) {
			/* This registrar only currently supports sip: and sips: URI schemes */
			continue;
		}

		expiration = registrar_get_expiration(aor, contact_hdr, rdata);
		details.uri = pjsip_uri_get_uri(contact_hdr->uri);
		pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, details.uri, contact_uri, sizeof(contact_uri));

		if (!(contact = ao2_callback(contacts, OBJ_UNLINK, registrar_find_contact, &details))) {
			/* If they are actually trying to delete a contact that does not exist... be forgiving */
			if (!expiration) {
				ast_verb(3, "Attempted to remove non-existent contact '%s' from AOR '%s' by request\n",
					contact_uri, aor_name);
				continue;
			}

			if (ast_sip_location_add_contact_nolock(aor, contact_uri, ast_tvadd(ast_tvnow(),
				ast_samp2tv(expiration, 1)), path_str ? ast_str_buffer(path_str) : NULL,
					user_agent, via_addr, via_port, call_id, endpoint)) {
				ast_log(LOG_ERROR, "Unable to bind contact '%s' to AOR '%s'\n",
						contact_uri, aor_name);
				continue;
			}

			ast_verb(3, "Added contact '%s' to AOR '%s' with expiration of %d seconds\n",
				contact_uri, aor_name, expiration);
			ast_test_suite_event_notify("AOR_CONTACT_ADDED",
					"Contact: %s\r\n"
					"AOR: %s\r\n"
					"Expiration: %d\r\n"
					"UserAgent: %s",
					contact_uri,
					aor_name,
					expiration,
					user_agent);
		} else if (expiration) {
			struct ast_sip_contact *contact_update;

			contact_update = ast_sorcery_copy(ast_sip_get_sorcery(), contact);
			if (!contact_update) {
				ast_log(LOG_ERROR, "Failed to update contact '%s' expiration time to %d seconds.\n",
					contact->uri, expiration);
				continue;
			}

			contact_update->expiration_time = ast_tvadd(ast_tvnow(), ast_samp2tv(expiration, 1));
			contact_update->qualify_frequency = aor->qualify_frequency;
			contact_update->authenticate_qualify = aor->authenticate_qualify;
			if (path_str) {
				ast_string_field_set(contact_update, path, ast_str_buffer(path_str));
			}
			if (user_agent) {
				ast_string_field_set(contact_update, user_agent, user_agent);
			}
			if (!ast_strlen_zero(ast_config_AST_SYSTEM_NAME)) {
				ast_string_field_set(contact_update, reg_server, ast_config_AST_SYSTEM_NAME);
			}

			if (ast_sip_location_update_contact(contact_update)) {
				ast_log(LOG_ERROR, "Failed to update contact '%s' expiration time to %d seconds.\n",
					contact->uri, expiration);
				ast_sip_location_delete_contact(contact);
				continue;
			}
			ast_debug(3, "Refreshed contact '%s' on AOR '%s' with new expiration of %d seconds\n",
				contact_uri, aor_name, expiration);
			ast_test_suite_event_notify("AOR_CONTACT_REFRESHED",
					"Contact: %s\r\n"
					"AOR: %s\r\n"
					"Expiration: %d\r\n"
					"UserAgent: %s",
					contact_uri,
					aor_name,
					expiration,
					contact_update->user_agent);
			ao2_cleanup(contact_update);
		} else {
			/* We want to report the user agent that was actually in the removed contact */
			ast_sip_location_delete_contact(contact);
			ast_verb(3, "Removed contact '%s' from AOR '%s' due to request\n", contact_uri, aor_name);
			ast_test_suite_event_notify("AOR_CONTACT_REMOVED",
					"Contact: %s\r\n"
					"AOR: %s\r\n"
					"UserAgent: %s",
					contact_uri,
					aor_name,
					contact->user_agent);
		}
	}

	pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), details.pool);

	/* If the AOR is configured to remove any existing contacts that have not been updated/added as a result of this REGISTER
	 * do so
	 */
	if (aor->remove_existing) {
		ao2_callback(contacts, OBJ_NODATA | OBJ_MULTIPLE, registrar_delete_contact, NULL);
	}

	/* Re-retrieve contacts.  Caller will clean up the original container. */
	contacts = ast_sip_location_retrieve_aor_contacts_nolock(aor);
	response_contact = ao2_callback(contacts, 0, NULL, NULL);

	/* Send a response containing all of the contacts (including static) that are present on this AOR */
	if (ast_sip_create_response(rdata, 200, response_contact, &tdata) != PJ_SUCCESS) {
		ao2_cleanup(response_contact);
		ao2_cleanup(contacts);
		return PJ_TRUE;
	}
	ao2_cleanup(response_contact);

	/* Add the date header to the response, some UAs use this to set their date and time */
	registrar_add_date_header(tdata);

	ao2_callback(contacts, 0, registrar_add_contact, tdata);
	ao2_cleanup(contacts);

	if ((expires_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, NULL))) {
		expires_hdr = pjsip_expires_hdr_create(tdata->pool, registrar_get_expiration(aor, NULL, rdata));
		pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)expires_hdr);
	}

	ast_sip_send_stateful_response(rdata, tdata, endpoint);

	return PJ_TRUE;
}
Exemple #13
0
/*
 * This is the handler to receive message for this test. It is used to
 * control and verify the behavior of the message transmitted by the
 * transaction.
 */
static pj_bool_t msg_receiver_on_rx_request(pjsip_rx_data *rdata)
{
    if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST1_BRANCH_ID) == 0) {
	/*
	 * The TEST1_BRANCH_ID test performs the verifications for transaction
	 * retransmission mechanism. It will not answer the incoming request
	 * with any response.
	 */
	pjsip_msg *msg = rdata->msg_info.msg;

	PJ_LOG(4,(THIS_FILE, "    received request"));

	/* Only wants to take INVITE or OPTIONS method. */
	if (msg->line.req.method.id != PJSIP_INVITE_METHOD &&
	    msg->line.req.method.id != PJSIP_OPTIONS_METHOD)
	{
	    PJ_LOG(3,(THIS_FILE, "    error: received unexpected method %.*s",
			  msg->line.req.method.name.slen,
			  msg->line.req.method.name.ptr));
	    test_complete = -600;
	    return PJ_TRUE;
	}

	if (recv_count == 0) {
	    recv_count++;
	    //pj_gettimeofday(&recv_last);
	    recv_last = rdata->pkt_info.timestamp;
	} else {
	    pj_time_val now;
	    unsigned msec_expected, msec_elapsed;
	    int max_received;

	    //pj_gettimeofday(&now);
	    now = rdata->pkt_info.timestamp;
	    PJ_TIME_VAL_SUB(now, recv_last);
	    msec_elapsed = now.sec*1000 + now.msec;

	    ++recv_count;
    	    msec_expected = (1<<(recv_count-2))*PJSIP_T1_TIMEOUT;

	    if (msg->line.req.method.id != PJSIP_INVITE_METHOD) {
		if (msec_expected > PJSIP_T2_TIMEOUT)
		    msec_expected = PJSIP_T2_TIMEOUT;
		max_received = 11;
	    } else {
		max_received = 7;
	    }

	    if (DIFF(msec_expected, msec_elapsed) > TEST1_ALLOWED_DIFF) {
		PJ_LOG(3,(THIS_FILE,
			  "    error: expecting retransmission no. %d in %d "
			  "ms, received in %d ms",
			  recv_count-1, msec_expected, msec_elapsed));
		test_complete = -610;
	    }

	    
	    if (recv_count > max_received) {
		PJ_LOG(3,(THIS_FILE, 
			  "    error: too many messages (%d) received",
			  recv_count));
		test_complete = -620;
	    }

	    //pj_gettimeofday(&recv_last);
	    recv_last = rdata->pkt_info.timestamp;
	}
	return PJ_TRUE;

    } else
    if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST4_BRANCH_ID) == 0) {
	/*
	 * The TEST4_BRANCH_ID test simulates transport failure after several
	 * retransmissions.
	 */
	recv_count++;

	if (recv_count == TEST4_RETRANSMIT_CNT) {
	    /* Simulate transport failure. */
	    pjsip_loop_set_failure(loop, 2, NULL);

	} else if (recv_count > TEST4_RETRANSMIT_CNT) {
	    PJ_LOG(3,(THIS_FILE,"   error: not expecting %d-th packet!",
		      recv_count));
	    test_complete = -631;
	}

	return PJ_TRUE;


    } else
    if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST5_BRANCH_ID) == 0) {
	/*
	 * The TEST5_BRANCH_ID test simulates user terminating the transaction
	 * after several retransmissions.
	 */
	recv_count++;

	if (recv_count == TEST5_RETRANSMIT_CNT+1) {
	    pj_str_t key;
	    pjsip_transaction *tsx;

	    pjsip_tsx_create_key( rdata->tp_info.pool, &key, PJSIP_ROLE_UAC,
				  &rdata->msg_info.msg->line.req.method, rdata);
	    tsx = pjsip_tsx_layer_find_tsx(&key, PJ_TRUE);
	    if (tsx) {
		pjsip_tsx_terminate(tsx, PJSIP_SC_REQUEST_TERMINATED);
		pj_mutex_unlock(tsx->mutex);
	    } else {
		PJ_LOG(3,(THIS_FILE, "    error: uac transaction not found!"));
		test_complete = -633;
	    }

	} else if (recv_count > TEST5_RETRANSMIT_CNT+1) {
	    PJ_LOG(3,(THIS_FILE,"   error: not expecting %d-th packet!",
		      recv_count));
	    test_complete = -634;
	}

	return PJ_TRUE;

    } else
    if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST6_BRANCH_ID) == 0) {
	/*
	 * The TEST6_BRANCH_ID test successfull non-INVITE transaction.
	 */
	pj_status_t status;

	recv_count++;

	if (recv_count > 1) {
	    PJ_LOG(3,(THIS_FILE,"   error: not expecting %d-th packet!",
		      recv_count));
	    test_complete = -635;
	}

	status = pjsip_endpt_respond_stateless(endpt, rdata, 202, NULL,
					       NULL, NULL);
	if (status != PJ_SUCCESS) {
	    app_perror("    error: unable to send response", status);
	    test_complete = -636;
	}

	return PJ_TRUE;


    } else
    if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST7_BRANCH_ID) == 0) {
	/*
	 * The TEST7_BRANCH_ID test successfull non-INVITE transaction
	 * with provisional response.
	 */
	pj_status_t status;
	pjsip_response_addr res_addr;
	struct response *r;
	pjsip_tx_data *tdata;
	pj_time_val delay = { 2, 0 };

	recv_count++;

	if (recv_count > 1) {
	    PJ_LOG(3,(THIS_FILE,"   error: not expecting %d-th packet!",
		      recv_count));
	    test_complete = -640;
	    return PJ_TRUE;
	}

	/* Respond with provisional response */
	status = pjsip_endpt_create_response(endpt, rdata, 100, NULL, &tdata);
	pj_assert(status == PJ_SUCCESS);

	status = pjsip_get_response_addr(tdata->pool, rdata, &res_addr);
	pj_assert(status == PJ_SUCCESS);

	status = pjsip_endpt_send_response(endpt, &res_addr, tdata, 
					   NULL, NULL);
	pj_assert(status == PJ_SUCCESS);

	/* Create the final response. */
	status = pjsip_endpt_create_response(endpt, rdata, 202, NULL, &tdata);
	pj_assert(status == PJ_SUCCESS);

	/* Schedule sending final response in couple of of secs. */
	r = pj_pool_alloc(tdata->pool, sizeof(*r));
	r->res_addr = res_addr;
	r->tdata = tdata;
	if (r->res_addr.transport)
	    pjsip_transport_add_ref(r->res_addr.transport);

	timer.entry.cb = &send_response_callback;
	timer.entry.user_data = r;
	pjsip_endpt_schedule_timer(endpt, &timer.entry, &delay);

	return PJ_TRUE;


    } else
    if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST8_BRANCH_ID) == 0) {
	/*
	 * The TEST8_BRANCH_ID test failed INVITE transaction.
	 */
	pjsip_method *method;
	pj_status_t status;

	method = &rdata->msg_info.msg->line.req.method;

	recv_count++;

	if (method->id == PJSIP_INVITE_METHOD) {

	    if (recv_count > 1) {
		PJ_LOG(3,(THIS_FILE,"   error: not expecting %d-th packet!",
			  recv_count));
		test_complete = -635;
	    }

	    status = pjsip_endpt_respond_stateless(endpt, rdata, 301, NULL,
						   NULL, NULL);
	    if (status != PJ_SUCCESS) {
		app_perror("    error: unable to send response", status);
		test_complete = -636;
	    }

	} else if (method->id == PJSIP_ACK_METHOD) {

	    if (recv_count == 2) {
		pj_str_t key;
		pj_time_val delay = { 5, 0 };
		
		/* Schedule timer to destroy transaction after 5 seconds.
		 * This is to make sure that transaction does not 
		 * retransmit ACK.
		 */
		pjsip_tsx_create_key(rdata->tp_info.pool, &key,
				     PJSIP_ROLE_UAC, &pjsip_invite_method,
				     rdata);

		pj_strcpy(&timer.tsx_key, &key);
		timer.entry.id = 301;
		timer.entry.cb = &terminate_tsx_callback;

		pjsip_endpt_schedule_timer(endpt, &timer.entry, &delay);
	    }

	    if (recv_count > 2) {
		PJ_LOG(3,(THIS_FILE,"   error: not expecting %d-th packet!",
			  recv_count));
		test_complete = -638;
	    }


	} else {
	    PJ_LOG(3,(THIS_FILE,"   error: not expecting %s",
		      pjsip_rx_data_get_info(rdata)));
	    test_complete = -639;

	}


    } else
    if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST9_BRANCH_ID) == 0) {
	/*
	 * The TEST9_BRANCH_ID test failed INVITE transaction with
	 * provisional response.
	 */
	pjsip_method *method;
	pj_status_t status;

	method = &rdata->msg_info.msg->line.req.method;

	recv_count++;

	if (method->id == PJSIP_INVITE_METHOD) {

	    pjsip_response_addr res_addr;
	    struct response *r;
	    pjsip_tx_data *tdata;
	    pj_time_val delay = { 2, 0 };

	    if (recv_count > 1) {
		PJ_LOG(3,(THIS_FILE,"   error: not expecting %d-th packet!",
			  recv_count));
		test_complete = -650;
		return PJ_TRUE;
	    }

	    /* Respond with provisional response */
	    status = pjsip_endpt_create_response(endpt, rdata, 100, NULL, 
						 &tdata);
	    pj_assert(status == PJ_SUCCESS);

	    status = pjsip_get_response_addr(tdata->pool, rdata, &res_addr);
	    pj_assert(status == PJ_SUCCESS);

	    status = pjsip_endpt_send_response(endpt, &res_addr, tdata, 
					       NULL, NULL);
	    pj_assert(status == PJ_SUCCESS);

	    /* Create the final response. */
	    status = pjsip_endpt_create_response(endpt, rdata, 302, NULL, 
						 &tdata);
	    pj_assert(status == PJ_SUCCESS);

	    /* Schedule sending final response in couple of of secs. */
	    r = pj_pool_alloc(tdata->pool, sizeof(*r));
	    r->res_addr = res_addr;
	    r->tdata = tdata;
	    if (r->res_addr.transport)
		pjsip_transport_add_ref(r->res_addr.transport);

	    timer.entry.cb = &send_response_callback;
	    timer.entry.user_data = r;
	    pjsip_endpt_schedule_timer(endpt, &timer.entry, &delay);

	} else if (method->id == PJSIP_ACK_METHOD) {

	    if (recv_count == 2) {
		pj_str_t key;
		pj_time_val delay = { 5, 0 };
		
		/* Schedule timer to destroy transaction after 5 seconds.
		 * This is to make sure that transaction does not 
		 * retransmit ACK.
		 */
		pjsip_tsx_create_key(rdata->tp_info.pool, &key,
				     PJSIP_ROLE_UAC, &pjsip_invite_method,
				     rdata);

		pj_strcpy(&timer.tsx_key, &key);
		timer.entry.id = 302;
		timer.entry.cb = &terminate_tsx_callback;

		pjsip_endpt_schedule_timer(endpt, &timer.entry, &delay);
	    }

	    if (recv_count > 2) {
		PJ_LOG(3,(THIS_FILE,"   error: not expecting %d-th packet!",
			  recv_count));
		test_complete = -638;
	    }


	} else {
	    PJ_LOG(3,(THIS_FILE,"   error: not expecting %s",
		      pjsip_rx_data_get_info(rdata)));
	    test_complete = -639;

	}

	return PJ_TRUE;

    }

    return PJ_FALSE;
}
Exemple #14
0
/*
 Cualquier REQUEST SIP pasa por aquí
 Aquí es dónde hacemos la magia negra de coger la header, desencapsular y tal
 */
static pj_bool_t on_rx_request( pjsip_rx_data *rdata )
{


	if (  (rdata->msg_info.msg->line.req.method.id != PJSIP_OPTIONS_METHOD))
	{
		debug(2,"Received no OPTIONS Request, reply 500 sent");
		pj_str_t reason = pj_str("Go home");
		pjsip_endpt_respond_stateless( g_endpt, rdata,500, &reason,NULL, NULL);
		return PJ_TRUE;
	}
	debug(1,"Received INFO/OPTIONS Request, lets parse it");
	
	pjsip_cid_hdr *headerMultivpn;
	pj_str_t hdrname = { .ptr = "Multivpn", .slen = 8 };
	
	headerMultivpn = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg ,&hdrname,NULL);
	
	if (!headerMultivpn)
	{
		debug(2,"No multivpn header found! Nothing to parse");
		pj_str_t reason = pj_str("Go home and sleep");
		pjsip_endpt_respond_stateless( g_endpt, rdata,500, &reason,NULL, NULL);
		return PJ_TRUE;
	}	
	else debug(1,"Header multivpn found ! Lets play with it");
	

    char payload[2048];
    memset(payload, 0, sizeof(payload));
    strncpy(payload, headerMultivpn->id.ptr, headerMultivpn->id.slen);
	
	debug(1,"Received payload is: %s with len %d",payload,strlen(payload));
	
	
	unsigned char *decodedpayload;
	size_t lenDecoded;
	decodedpayload = base64_decode(payload,strlen(payload),&lenDecoded);
	debug(1,"Decoded %d bytes",lenDecoded);
	debug(1,"Decoded payload with len %d and value %.3s",lenDecoded, decodedpayload);
	
	debug(1,"Now sending to PIPE for TUNDRIVER !");

	int nBytes = lenDecoded;
	
	nBytes=write(global_v.pipe_from_plugin[1],decodedpayload,nBytes);
	if (nBytes<=0)
		debug(3,"SIP Plugin: Failed Writing to Pipe");
	else    debug(3,"SIP Plugin: Write %d bytes to pipe",nBytes);
                
	// Tras el parsing, contestamos:
	pj_str_t reason = pj_str("Traffic Accepted");
   pjsip_endpt_respond_stateless( g_endpt, rdata,666, &reason,NULL, NULL);
   
   debug(1,"End process of request");
	return PJ_TRUE;



}

 
int sip_envia_datos(unsigned char *datos,int longitud)
{
	debug(1,"Starting function to send %d bytes", longitud);
	
	debug(1,"Now base64 encoding %d bytes",longitud);

	int longitudEncodeado;                    
	char * payload;
	payload = base64_encode(datos,longitud,(size_t *)&longitudEncodeado);
	                    	
	pj_status_t status;
	pjsip_tx_data *tdata;
	pj_str_t target = pj_str(global_v.sip_remoteuri);
	pj_str_t from = pj_str(global_v.sip_fromuri);

	status = pjsip_endpt_create_request(
			g_endpt,
			&pjsip_options_method,
			&target,
			&from,
			&target,
			NULL,
			NULL,
			-1,
			NULL,
			&tdata
	);
	PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);

	pjsip_transaction *tsx;
	status = pjsip_tsx_create_uac(NULL, tdata, &tsx);
	PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);

	// Create Custom header
	pj_str_t hdr_name = { .ptr = "Multivpn", .slen = 8 };
	pj_str_t hdr_value = { .ptr = payload, .slen = longitudEncodeado };
	pjsip_generic_string_hdr *multivpn_hdr = pjsip_generic_string_hdr_create(
			tdata->pool,
			&hdr_name,
			&hdr_value
	);

	// Add to message
	pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) multivpn_hdr);


	status = pjsip_tsx_send_msg(tsx, NULL);
	PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);

	return 0;
}



void* sip_loop_sip_events(void *none)
{
    for (;!g_complete;) {
			//pj_time_val timeout = {0, 10};
			//pjsip_endpt_handle_events(g_endpt, &timeout);
			pjsip_endpt_handle_events(g_endpt, NULL);
			debug(1,"Looping SIP");
    }

    return NULL;
 }

void sip_loop_tun_events()
{
	 unsigned char buffer[BLOCK_SIZE];
    int nBytes;
    fd_set  setReading;
    int maxfd;
    
    debug(2,"SIP Plugin: Starting LOOPING for events from TUN");
     maxfd = global_v.pipe_to_plugin[0]+1;
    while (1)
    {
        FD_SET(global_v.pipe_to_plugin[0],&setReading);
        debug(3,"SIP Plugin: Blocking now, until data from tundriver is received");
        
        select(maxfd,&setReading,NULL,NULL,NULL);

			debug(1,"SIP PLUGIN: Select unlocked !");
			        
        if (FD_ISSET(global_v.pipe_to_plugin[0],&setReading))
        {
            // Message is from pipe
            nBytes=read(global_v.pipe_to_plugin[0],buffer, BLOCK_SIZE-1);
            if (nBytes<=0)
                debug(3,"SIP Plugin: failed reading From Pipe");
            else    
            {
                debug(3,"SIP Plugin: Read %d bytes from pipe",nBytes);
         		 sip_envia_datos(buffer,nBytes);
            
        		}
        
    		}
    }
 }
Exemple #15
0
static pj_bool_t distributor(pjsip_rx_data *rdata)
{
	pjsip_dialog *dlg;
	struct distributor_dialog_data *dist = NULL;
	struct ast_taskprocessor *serializer = NULL;
	pjsip_rx_data *clone;

	if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
		/*
		 * Ignore everything until we are fully booted.  Let the
		 * peer retransmit messages until we are ready.
		 */
		return PJ_TRUE;
	}

	dlg = find_dialog(rdata);
	if (dlg) {
		ast_debug(3, "Searching for serializer associated with dialog %s for %s\n",
			dlg->obj_name, pjsip_rx_data_get_info(rdata));
		dist = ao2_find(dialog_associations, dlg, OBJ_SEARCH_KEY);
		if (dist) {
			ao2_lock(dist);
			serializer = ao2_bump(dist->serializer);
			ao2_unlock(dist);
			if (serializer) {
				ast_debug(3, "Found serializer %s associated with dialog %s\n",
					ast_taskprocessor_name(serializer), dlg->obj_name);
			}
		}
	}

	if (serializer) {
		/* We have a serializer so we know where to send the message. */
	} else if (rdata->msg_info.msg->type == PJSIP_RESPONSE_MSG) {
		ast_debug(3, "No dialog serializer for %s.  Using request transaction as basis.\n",
			pjsip_rx_data_get_info(rdata));
		serializer = find_request_serializer(rdata);
		if (!serializer) {
			/*
			 * Pick a serializer for the unmatched response.
			 * We couldn't determine what serializer originally
			 * sent the request or the serializer is gone.
			 */
			serializer = ast_sip_get_distributor_serializer(rdata);
		}
	} else if (!pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_cancel_method)
		|| !pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_bye_method)) {
		/* We have a BYE or CANCEL request without a serializer. */
		pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata,
			PJSIP_SC_CALL_TSX_DOES_NOT_EXIST, NULL, NULL, NULL);
		ao2_cleanup(dist);
		return PJ_TRUE;
	} else {
		if (ast_taskprocessor_alert_get()) {
			/*
			 * When taskprocessors get backed up, there is a good chance that
			 * we are being overloaded and need to defer adding new work to
			 * the system.  To defer the work we will ignore the request and
			 * rely on the peer's transport layer to retransmit the message.
			 * We usually work off the overload within a few seconds.  The
			 * alternative is to send back a 503 response to these requests
			 * and be done with it.
			 */
			ast_debug(3, "Taskprocessor overload alert: Ignoring '%s'.\n",
				pjsip_rx_data_get_info(rdata));
			ao2_cleanup(dist);
			return PJ_TRUE;
		}

		/* Pick a serializer for the out-of-dialog request. */
		serializer = ast_sip_get_distributor_serializer(rdata);
	}

	if (pjsip_rx_data_clone(rdata, 0, &clone) != PJ_SUCCESS) {
		ast_taskprocessor_unreference(serializer);
		ao2_cleanup(dist);
		return PJ_TRUE;
	}

	if (dist) {
		ao2_lock(dist);
		clone->endpt_info.mod_data[endpoint_mod.id] = ao2_bump(dist->endpoint);
		ao2_unlock(dist);
		ao2_cleanup(dist);
	}

	if (ast_sip_push_task(serializer, distribute, clone)) {
		ao2_cleanup(clone->endpt_info.mod_data[endpoint_mod.id]);
		pjsip_rx_data_free_cloned(clone);
	}

	ast_taskprocessor_unreference(serializer);

	return PJ_TRUE;
}
static int register_aor(pjsip_rx_data *rdata,
	struct ast_sip_endpoint *endpoint,
	struct ast_sip_aor *aor,
	const char *aor_name)
{
	struct aor_core_response response = {
		.code = 500,
	};
	struct ao2_container *contacts = NULL;

	ao2_lock(aor);
	contacts = ast_sip_location_retrieve_aor_contacts_nolock(aor);
	if (!contacts) {
		ao2_unlock(aor);
		pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(),
			rdata, response.code, NULL, NULL, NULL);
		return PJ_TRUE;
	}

	register_aor_core(rdata, endpoint, aor, aor_name, contacts, &response);
	ao2_cleanup(contacts);
	ao2_unlock(aor);

	/* Now send the REGISTER response to the peer */
	if (response.tdata) {
		ast_sip_send_stateful_response(rdata, response.tdata, endpoint);
	} else {
		pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(),
			rdata, response.code, NULL, NULL, NULL);
	}
	return PJ_TRUE;
}

static int match_aor(const char *aor_name, const char *id)
{
	if (ast_strlen_zero(aor_name)) {
		return 0;
	}

	if (!strcmp(aor_name, id)) {
		ast_debug(3, "Matched id '%s' to aor '%s'\n", id, aor_name);
		return 1;
	}

	return 0;
}

static char *find_aor_name(const char *username, const char *domain, const char *aors)
{
	char *configured_aors;
	char *aors_buf;
	char *aor_name;
	char *id_domain;
	struct ast_sip_domain_alias *alias;

	id_domain = ast_alloca(strlen(username) + strlen(domain) + 2);
	sprintf(id_domain, "%s@%s", username, domain);

	aors_buf = ast_strdupa(aors);

	/* Look for exact match on username@domain */
	configured_aors = aors_buf;
	while ((aor_name = ast_strip(strsep(&configured_aors, ",")))) {
		if (match_aor(aor_name, id_domain)) {
			return ast_strdup(aor_name);
		}
	}

	/* If there's a domain alias, look for exact match on username@domain_alias */
	alias = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "domain_alias", domain);
	if (alias) {
		char *id_domain_alias = ast_alloca(strlen(username) + strlen(alias->domain) + 2);

		sprintf(id_domain, "%s@%s", username, alias->domain);
		ao2_cleanup(alias);

		configured_aors = strcpy(aors_buf, aors);/* Safe */
		while ((aor_name = ast_strip(strsep(&configured_aors, ",")))) {
			if (match_aor(aor_name, id_domain_alias)) {
				return ast_strdup(aor_name);
			}
		}
	}

	if (ast_strlen_zero(username)) {
		/* No username, no match */
		return NULL;
	}

	/* Look for exact match on username only */
	configured_aors = strcpy(aors_buf, aors);/* Safe */
	while ((aor_name = ast_strip(strsep(&configured_aors, ",")))) {
		if (match_aor(aor_name, username)) {
			return ast_strdup(aor_name);
		}
	}

	return NULL;
}
static pj_bool_t registrar_on_rx_request(struct pjsip_rx_data *rdata)
{
	RAII_VAR(struct serializer *, ser, NULL, ao2_cleanup);
	struct rx_task_data *task_data;

	RAII_VAR(struct ast_sip_endpoint *, endpoint,
		 ast_pjsip_rdata_get_endpoint(rdata), ao2_cleanup);
	RAII_VAR(struct ast_sip_aor *, aor, NULL, ao2_cleanup);
	pjsip_sip_uri *uri;
	char user_name[64], domain_name[64];
	char *configured_aors, *aor_name;

	if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_register_method) || !endpoint) {
		return PJ_FALSE;
	}

	if (ast_strlen_zero(endpoint->aors)) {
		/* Short circuit early if the endpoint has no AORs configured on it, which means no registration possible */
		pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 403, NULL, NULL, NULL);
		ast_sip_report_failed_acl(endpoint, rdata, "registrar_attempt_without_configured_aors");
		ast_log(LOG_WARNING, "Endpoint '%s' has no configured AORs\n", ast_sorcery_object_get_id(endpoint));
		return PJ_TRUE;
	}

	if (!PJSIP_URI_SCHEME_IS_SIP(rdata->msg_info.to->uri) && !PJSIP_URI_SCHEME_IS_SIPS(rdata->msg_info.to->uri)) {
		pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 416, NULL, NULL, NULL);
		ast_sip_report_failed_acl(endpoint, rdata, "registrar_invalid_uri_in_to_received");
		ast_log(LOG_WARNING, "Endpoint '%s' attempted to register to an AOR with a non-SIP URI\n", ast_sorcery_object_get_id(endpoint));
		return PJ_TRUE;
	}

	uri = pjsip_uri_get_uri(rdata->msg_info.to->uri);
	ast_copy_pj_str(user_name, &uri->user, sizeof(user_name));
	ast_copy_pj_str(domain_name, &uri->host, sizeof(domain_name));

	configured_aors = ast_strdupa(endpoint->aors);

	/* Iterate the configured AORs to see if the user or the user+domain match */
	while ((aor_name = strsep(&configured_aors, ","))) {
		char id[AST_UUID_STR_LEN];
		RAII_VAR(struct ast_sip_domain_alias *, alias, NULL, ao2_cleanup);

		snprintf(id, sizeof(id), "%s@%s", user_name, domain_name);
		if (!strcmp(aor_name, id)) {
			break;
		}

		if ((alias = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "domain_alias", domain_name))) {
			snprintf(id, sizeof(id), "%s@%s", user_name, alias->domain);
			if (!strcmp(aor_name, id)) {
				break;
			}
		}

		if (!strcmp(aor_name, user_name)) {
			break;
		}
	}

	if (ast_strlen_zero(aor_name) || !(aor = ast_sip_location_retrieve_aor(aor_name))) {
		/* The provided AOR name was not found (be it within the configuration or sorcery itself) */
		pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 404, NULL, NULL, NULL);
		ast_sip_report_req_no_support(endpoint, rdata, "registrar_requested_aor_not_found");
		ast_log(LOG_WARNING, "AOR '%s' not found for endpoint '%s'\n", user_name, ast_sorcery_object_get_id(endpoint));
		return PJ_TRUE;
	}

	if (!aor->max_contacts) {
		/* Registration is not permitted for this AOR */
		pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 403, NULL, NULL, NULL);
		ast_sip_report_req_no_support(endpoint, rdata, "registrar_attempt_without_registration_permitted");
		ast_log(LOG_WARNING, "AOR '%s' has no configured max_contacts. Endpoint '%s' unable to register\n",
				ast_sorcery_object_get_id(aor), ast_sorcery_object_get_id(endpoint));
		return PJ_TRUE;
	}

	if (!(ser = serializer_find_or_create(aor_name))) {
		pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 403, NULL, NULL, NULL);
		ast_sip_report_mem_limit(endpoint, rdata);
		ast_log(LOG_WARNING, "Endpoint '%s' unable to register on AOR '%s' - could not get serializer\n",
			ast_sorcery_object_get_id(endpoint), ast_sorcery_object_get_id(aor));
		return PJ_TRUE;
	}

	if (!(task_data = rx_task_data_create(rdata, endpoint, aor))) {
		pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 403, NULL, NULL, NULL);
		ast_sip_report_mem_limit(endpoint, rdata);
		ast_log(LOG_WARNING, "Endpoint '%s' unable to register on AOR '%s' - could not create rx_task_data\n",
			ast_sorcery_object_get_id(endpoint), ast_sorcery_object_get_id(aor));
		return PJ_TRUE;
	}

	if (ast_sip_push_task(ser->serializer, rx_task, task_data)) {
		pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 403, NULL, NULL, NULL);
		ast_sip_report_mem_limit(endpoint, rdata);
		ast_log(LOG_WARNING, "Endpoint '%s' unable to register on AOR '%s' - could not serialize task\n",
			ast_sorcery_object_get_id(endpoint), ast_sorcery_object_get_id(aor));
		ao2_ref(task_data, -1);
	}
	return PJ_TRUE;
}
/* Callback to be called to handle new incoming requests. */
static pj_bool_t proxy_on_rx_request( pjsip_rx_data *rdata )
{
    pjsip_transaction *uas_tsx, *uac_tsx;
    struct uac_data *uac_data;
    struct uas_data *uas_data;
    pjsip_tx_data *tdata;
    pj_status_t status;

    if (rdata->msg_info.msg->line.req.method.id != PJSIP_CANCEL_METHOD) {

	/* Verify incoming request */
	status = proxy_verify_request(rdata);
	if (status != PJ_SUCCESS) {
	    app_perror("RX invalid request", status);
	    return PJ_TRUE;
	}

	/*
	 * Request looks sane, next clone the request to create transmit data.
	 */
	status = pjsip_endpt_create_request_fwd(global.endpt, rdata, NULL,
						NULL, 0, &tdata);
	if (status != PJ_SUCCESS) {
	    pjsip_endpt_respond_stateless(global.endpt, rdata,
					  PJSIP_SC_INTERNAL_SERVER_ERROR, 
					  NULL, NULL, NULL);
	    return PJ_TRUE;
	}


	/* Process routing */
	status = proxy_process_routing(tdata);
	if (status != PJ_SUCCESS) {
	    app_perror("Error processing route", status);
	    return PJ_TRUE;
	}

	/* Calculate target */
	status = proxy_calculate_target(rdata, tdata);
	if (status != PJ_SUCCESS) {
	    app_perror("Error calculating target", status);
	    return PJ_TRUE;
	}

	/* Everything is set to forward the request. */

	/* If this is an ACK request, forward statelessly.
	 * This happens if the proxy records route and this ACK
	 * is sent for 2xx response. An ACK that is sent for non-2xx
	 * final response will be absorbed by transaction layer, and
	 * it will not be received by on_rx_request() callback.
	 */
	if (tdata->msg->line.req.method.id == PJSIP_ACK_METHOD) {
	    status = pjsip_endpt_send_request_stateless(global.endpt, tdata, 
							NULL, NULL);
	    if (status != PJ_SUCCESS) {
		app_perror("Error forwarding request", status);
		return PJ_TRUE;
	    }

	    return PJ_TRUE;
	}

	/* Create UAC transaction for forwarding the request. 
	 * Set our module as the transaction user to receive further
	 * events from this transaction.
	 */
	status = pjsip_tsx_create_uac(&mod_tu, tdata, &uac_tsx);
	if (status != PJ_SUCCESS) {
	    pjsip_tx_data_dec_ref(tdata);
	    pjsip_endpt_respond_stateless(global.endpt, rdata, 
					  PJSIP_SC_INTERNAL_SERVER_ERROR, 
					  NULL, NULL, NULL);
	    return PJ_TRUE;
	}

	/* Create UAS transaction to handle incoming request */
	status = pjsip_tsx_create_uas(&mod_tu, rdata, &uas_tsx);
	if (status != PJ_SUCCESS) {
	    pjsip_tx_data_dec_ref(tdata);
	    pjsip_endpt_respond_stateless(global.endpt, rdata, 
					  PJSIP_SC_INTERNAL_SERVER_ERROR, 
					  NULL, NULL, NULL);
	    pjsip_tsx_terminate(uac_tsx, PJSIP_SC_INTERNAL_SERVER_ERROR);
	    return PJ_TRUE;
	}

	/* Feed the request to the UAS transaction to drive it's state 
	 * out of NULL state. 
	 */
	pjsip_tsx_recv_msg(uas_tsx, rdata);

	/* Attach a data to the UAC transaction, to be used to find the
	 * UAS transaction when we receive response in the UAC side.
	 */
	uac_data = (struct uac_data*)
		   pj_pool_alloc(uac_tsx->pool, sizeof(struct uac_data));
	uac_data->uas_tsx = uas_tsx;
	uac_tsx->mod_data[mod_tu.id] = (void*)uac_data;

	/* Attach data to the UAS transaction, to find the UAC transaction
	 * when cancelling INVITE request.
	 */
	uas_data = (struct uas_data*)
		    pj_pool_alloc(uas_tsx->pool, sizeof(struct uas_data));
	uas_data->uac_tsx = uac_tsx;
	uas_tsx->mod_data[mod_tu.id] = (void*)uas_data;

	/* Everything is setup, forward the request */
	status = pjsip_tsx_send_msg(uac_tsx, tdata);
	if (status != PJ_SUCCESS) {
	    pjsip_tx_data *err_res;

	    /* Fail to send request, for some reason */

	    /* Destroy transmit data */
	    pjsip_tx_data_dec_ref(tdata);

	    /* I think UAC transaction should have been destroyed when
	     * it fails to send request, so no need to destroy it.
	    pjsip_tsx_terminate(uac_tsx, PJSIP_SC_INTERNAL_SERVER_ERROR);
	     */

	    /* Send 500/Internal Server Error to UAS transaction */
	    pjsip_endpt_create_response(global.endpt, rdata,
					500, NULL, &err_res);
	    pjsip_tsx_send_msg(uas_tsx, err_res);

	    return PJ_TRUE;
	}

	/* Send 100/Trying if this is an INVITE */
	if (rdata->msg_info.msg->line.req.method.id == PJSIP_INVITE_METHOD) {
	    pjsip_tx_data *res100;

	    pjsip_endpt_create_response(global.endpt, rdata, 100, NULL, 
					&res100);
	    pjsip_tsx_send_msg(uas_tsx, res100);
	}

    } else {
	/* This is CANCEL request */
	pjsip_transaction *invite_uas;
	struct uas_data *uas_data;
	pj_str_t key;
	
	/* Find the UAS INVITE transaction */
	pjsip_tsx_create_key(rdata->tp_info.pool, &key, PJSIP_UAS_ROLE,
			     pjsip_get_invite_method(), rdata);
	invite_uas = pjsip_tsx_layer_find_tsx(&key, PJ_TRUE);
	if (!invite_uas) {
	    /* Invite transaction not found, respond CANCEL with 481 */
	    pjsip_endpt_respond_stateless(global.endpt, rdata, 481, NULL,
					  NULL, NULL);
	    return PJ_TRUE;
	}

	/* Respond 200 OK to CANCEL */
	pjsip_endpt_respond(global.endpt, NULL, rdata, 200, NULL, NULL,
			    NULL, NULL);

	/* Send CANCEL to cancel the UAC transaction.
	 * The UAS INVITE transaction will get final response when
	 * we receive final response from the UAC INVITE transaction.
	 */
	uas_data = (struct uas_data*) invite_uas->mod_data[mod_tu.id];
	if (uas_data->uac_tsx && uas_data->uac_tsx->status_code < 200) {
	    pjsip_tx_data *cancel;

	    pj_mutex_lock(uas_data->uac_tsx->mutex);

	    pjsip_endpt_create_cancel(global.endpt, uas_data->uac_tsx->last_tx,
				      &cancel);
	    pjsip_endpt_send_request(global.endpt, cancel, -1, NULL, NULL);

	    pj_mutex_unlock(uas_data->uac_tsx->mutex);
	}

	/* Unlock UAS tsx because it is locked in find_tsx() */
	pj_mutex_unlock(invite_uas->mutex);
    }

    return PJ_TRUE;
}
static pj_bool_t mod_call_on_rx_request(pjsip_rx_data *rdata)
{
    const pj_str_t call_user = { "2", 1 };
    pjsip_uri *uri;
    pjsip_sip_uri *sip_uri;
    struct call *call;
    pjsip_dialog *dlg;
    pjmedia_sdp_session *sdp;
    pjsip_tx_data *tdata;
    pj_bool_t has_initial = PJ_FALSE;
    pj_status_t status;

    uri = pjsip_uri_get_uri(rdata->msg_info.msg->line.req.uri);

    /* Only want to receive SIP/SIPS scheme */
    if (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))
	return PJ_FALSE;

    sip_uri = (pjsip_sip_uri*) uri;

    /* Only want to handle INVITE requests. */
    if (rdata->msg_info.msg->line.req.method.id != PJSIP_INVITE_METHOD) {
	return PJ_FALSE;
    }


    /* Check for matching user part. Incoming requests will be handled 
     * call-statefully if:
     *	- user part is "2", or
     *  - user part is not "0" nor "1" and method is INVITE.
     */
    if (pj_strcmp(&sip_uri->user, &call_user) == 0 ||
	sip_uri->user.slen != 1 ||
	(*sip_uri->user.ptr != '0' && *sip_uri->user.ptr != '1'))
    {
	/* Match */

    } else {
	return PJ_FALSE;
    }


    /* Verify that we can handle the request. */
    if (app.real_sdp) {
	unsigned options = 0;
	status = pjsip_inv_verify_request(rdata, &options, NULL, NULL,
					  app.sip_endpt, &tdata);
	if (status != PJ_SUCCESS) {

	    /*
	     * No we can't handle the incoming INVITE request.
	     */

	    if (tdata) {
		pjsip_response_addr res_addr;

		pjsip_get_response_addr(tdata->pool, rdata, &res_addr);
		pjsip_endpt_send_response(app.sip_endpt, &res_addr, tdata, 
					  NULL, NULL);

	    } else {

		/* Respond with 500 (Internal Server Error) */
		pjsip_endpt_respond_stateless(app.sip_endpt, rdata, 500, NULL,
					      NULL, NULL);
	    }

	    return PJ_TRUE;
	} 
    }

    /* Create UAS dialog */
    status = pjsip_dlg_create_uas( pjsip_ua_instance(), rdata,
				   &app.local_contact, &dlg);
    if (status != PJ_SUCCESS) {
	const pj_str_t reason = pj_str("Unable to create dialog");
	pjsip_endpt_respond_stateless( app.sip_endpt, rdata, 
				       500, &reason,
				       NULL, NULL);
	return PJ_TRUE;
    }

    /* Alloc call structure. */
    call = pj_pool_zalloc(dlg->pool, sizeof(struct call));

    /* Create SDP from PJMEDIA */
    if (app.real_sdp) {
	status = pjmedia_endpt_create_sdp(app.med_endpt, rdata->tp_info.pool, 
					  app.skinfo_cnt, app.skinfo, 
					  &sdp);
    } else {
	sdp = app.dummy_sdp;
    }

    /* Create UAS invite session */
    status = pjsip_inv_create_uas( dlg, rdata, sdp, 0, &call->inv);
    if (status != PJ_SUCCESS) {
	pjsip_dlg_create_response(dlg, rdata, 500, NULL, &tdata);
	pjsip_dlg_send_response(dlg, pjsip_rdata_get_tsx(rdata), tdata);
	return PJ_TRUE;
    }
    
    /* Send 100/Trying if needed */
    if (app.server.send_trying) {
	status = send_response(call->inv, rdata, 100, &has_initial);
	if (status != PJ_SUCCESS)
	    return PJ_TRUE;
    }

    /* Send 180/Ringing if needed */
    if (app.server.send_ringing) {
	status = send_response(call->inv, rdata, 180, &has_initial);
	if (status != PJ_SUCCESS)
	    return PJ_TRUE;
    }

    /* Simulate call processing delay */
    if (app.server.delay) {
	pj_time_val delay;

	call->ans_timer.id = 1;
	call->ans_timer.user_data = call;
	call->ans_timer.cb = &answer_timer_cb;
	
	delay.sec = 0;
	delay.msec = app.server.delay;
	pj_time_val_normalize(&delay);

	pjsip_endpt_schedule_timer(app.sip_endpt, &call->ans_timer, &delay);

    } else {
	/* Send the 200 response immediately . */  
	status = send_response(call->inv, rdata, 200, &has_initial);
	PJ_ASSERT_ON_FAIL(status == PJ_SUCCESS, return PJ_TRUE);
    }

    /* Done */
    app.server.cur_state.call_cnt++;

    return PJ_TRUE;
}
Exemple #20
0
static pj_bool_t endpoint_lookup(pjsip_rx_data *rdata)
{
	struct ast_sip_endpoint *endpoint;
	struct unidentified_request *unid;
	int is_ack = rdata->msg_info.msg->line.req.method.id == PJSIP_ACK_METHOD;

	endpoint = rdata->endpt_info.mod_data[endpoint_mod.id];
	if (endpoint) {
		/*
		 * ao2_find with OBJ_UNLINK always write locks the container before even searching
		 * for the object.  Since the majority case is that the object won't be found, do
		 * the find without OBJ_UNLINK to prevent the unnecessary write lock, then unlink
		 * if needed.
		 */
		unid = ao2_find(unidentified_requests, rdata->pkt_info.src_name, OBJ_SEARCH_KEY);
		if (unid) {
			ao2_unlink(unidentified_requests, unid);
			ao2_ref(unid, -1);
		}
		apply_acls(rdata);
		return PJ_FALSE;
	}

	endpoint = ast_sip_identify_endpoint(rdata);
	if (endpoint) {
		unid = ao2_find(unidentified_requests, rdata->pkt_info.src_name, OBJ_SEARCH_KEY);
		if (unid) {
			ao2_unlink(unidentified_requests, unid);
			ao2_ref(unid, -1);
		}
	}

	if (!endpoint) {
		/* always use an artificial endpoint - per discussion no reason
		   to have "alwaysauthreject" as an option.  It is felt using it
		   was a bug fix and it is not needed since we are not worried about
		   breaking old stuff and we really don't want to enable the discovery
		   of SIP accounts */
		endpoint = ast_sip_get_artificial_endpoint();
	}

	/* endpoint ref held by mod_data[] */
	rdata->endpt_info.mod_data[endpoint_mod.id] = endpoint;

	if (endpoint == artificial_endpoint && !is_ack) {
		char name[AST_UUID_STR_LEN] = "";
		pjsip_uri *from = rdata->msg_info.from->uri;

		if (PJSIP_URI_SCHEME_IS_SIP(from) || PJSIP_URI_SCHEME_IS_SIPS(from)) {
			pjsip_sip_uri *sip_from = pjsip_uri_get_uri(from);
			ast_copy_pj_str(name, &sip_from->user, sizeof(name));
		}

		unid = ao2_find(unidentified_requests, rdata->pkt_info.src_name, OBJ_SEARCH_KEY);
		if (unid) {
			check_endpoint(rdata, unid, name);
			ao2_ref(unid, -1);
		} else if (using_auth_username) {
			ao2_wrlock(unidentified_requests);
			/* Checking again with the write lock held allows us to eliminate the DUPS_REPLACE and sort_fn */
			unid = ao2_find(unidentified_requests, rdata->pkt_info.src_name,
				OBJ_SEARCH_KEY | OBJ_NOLOCK);
			if (unid) {
				check_endpoint(rdata, unid, name);
			} else {
				unid = ao2_alloc_options(sizeof(*unid) + strlen(rdata->pkt_info.src_name) + 1,
					NULL, AO2_ALLOC_OPT_LOCK_RWLOCK);
				if (!unid) {
					ao2_unlock(unidentified_requests);
					pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
					return PJ_TRUE;
				}
				strcpy(unid->src_name, rdata->pkt_info.src_name); /* Safe */
				unid->first_seen = ast_tvnow();
				unid->count = 1;
				ao2_link_flags(unidentified_requests, unid, OBJ_NOLOCK);
			}
			ao2_ref(unid, -1);
			ao2_unlock(unidentified_requests);
		} else {
			log_failed_request(rdata, "No matching endpoint found", 0, 0);
			ast_sip_report_invalid_endpoint(name, rdata);
		}
	}

	apply_acls(rdata);
	return PJ_FALSE;
}
Exemple #21
0
static int distribute(void *data)
{
	static pjsip_process_rdata_param param = {
		.start_mod = &distributor_mod,
		.idx_after_start = 1,
	};
	pj_bool_t handled = PJ_FALSE;
	pjsip_rx_data *rdata = data;
	int is_request = rdata->msg_info.msg->type == PJSIP_REQUEST_MSG;
	int is_ack = is_request ? rdata->msg_info.msg->line.req.method.id == PJSIP_ACK_METHOD : 0;
	struct ast_sip_endpoint *endpoint;

	pjsip_endpt_process_rx_data(ast_sip_get_pjsip_endpoint(), rdata, &param, &handled);
	if (!handled && is_request && !is_ack) {
		pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 501, NULL, NULL, NULL);
	}

	/* The endpoint_mod stores an endpoint reference in the mod_data of rdata. This
	 * is the only appropriate spot to actually decrement the reference.
	 */
	endpoint = rdata->endpt_info.mod_data[endpoint_mod.id];
	ao2_cleanup(endpoint);
	pjsip_rx_data_free_cloned(rdata);
	return 0;
}

struct ast_sip_endpoint *ast_pjsip_rdata_get_endpoint(pjsip_rx_data *rdata)
{
	struct ast_sip_endpoint *endpoint = rdata->endpt_info.mod_data[endpoint_mod.id];
	if (endpoint) {
		ao2_ref(endpoint, +1);
	}
	return endpoint;
}

static int suspects_sort(const void *obj, const void *arg, int flags)
{
	const struct unidentified_request *object_left = obj;
	const struct unidentified_request *object_right = arg;
	const char *right_key = arg;
	int cmp;

	switch (flags & OBJ_SEARCH_MASK) {
	case OBJ_SEARCH_OBJECT:
		right_key = object_right->src_name;
		/* Fall through */
	case OBJ_SEARCH_KEY:
		cmp = strcmp(object_left->src_name, right_key);
		break;
	case OBJ_SEARCH_PARTIAL_KEY:
		cmp = strncmp(object_left->src_name, right_key, strlen(right_key));
		break;
	default:
		cmp = 0;
		break;
	}
	return cmp;
}

static int suspects_compare(void *obj, void *arg, int flags)
{
	const struct unidentified_request *object_left = obj;
	const struct unidentified_request *object_right = arg;
	const char *right_key = arg;
	int cmp = 0;

	switch (flags & OBJ_SEARCH_MASK) {
	case OBJ_SEARCH_OBJECT:
		right_key = object_right->src_name;
		/* Fall through */
	case OBJ_SEARCH_KEY:
		if (strcmp(object_left->src_name, right_key) == 0) {
			cmp = CMP_MATCH;
		}
		break;
	case OBJ_SEARCH_PARTIAL_KEY:
		if (strncmp(object_left->src_name, right_key, strlen(right_key)) == 0) {
			cmp = CMP_MATCH;
		}
		break;
	default:
		cmp = 0;
		break;
	}
	return cmp;
}

static int suspects_hash(const void *obj, int flags)
{
	const struct unidentified_request *object;
	const char *key;

	switch (flags & OBJ_SEARCH_MASK) {
	case OBJ_SEARCH_KEY:
		key = obj;
		break;
	case OBJ_SEARCH_OBJECT:
		object = obj;
		key = object->src_name;
		break;
	default:
		/* Hash can only work on something with a full key. */
		ast_assert(0);
		return 0;
	}
	return ast_str_hash(key);
}

static struct ao2_container *cli_unid_get_container(const char *regex)
{
	struct ao2_container *s_container;

	s_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,
		suspects_sort, suspects_compare);
	if (!s_container) {
		return NULL;
	}

	if (ao2_container_dup(s_container, unidentified_requests, 0)) {
		ao2_ref(s_container, -1);
		return NULL;
	}

	return s_container;
}

static int cli_unid_iterate(void *container, ao2_callback_fn callback, void *args)
{
	ao2_callback(container, 0, callback, args);

	return 0;
}
static int rx_task(void *data)
{
	RAII_VAR(struct rx_task_data *, task_data, data, ao2_cleanup);
	RAII_VAR(struct ao2_container *, contacts, NULL, ao2_cleanup);

	int added = 0, updated = 0, deleted = 0;
	pjsip_contact_hdr *contact_hdr = NULL;
	struct registrar_contact_details details = { 0, };
	pjsip_tx_data *tdata;
	pjsip_response_addr addr;
	const char *aor_name = ast_sorcery_object_get_id(task_data->aor);

	/* Retrieve the current contacts, we'll need to know whether to update or not */
	contacts = ast_sip_location_retrieve_aor_contacts(task_data->aor);

	/* So we don't count static contacts against max_contacts we prune them out from the container */
	ao2_callback(contacts, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, registrar_prune_static, NULL);

	if (registrar_validate_contacts(task_data->rdata, contacts, task_data->aor, &added, &updated, &deleted)) {
		/* The provided Contact headers do not conform to the specification */
		pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), task_data->rdata, 400, NULL, NULL, NULL);
		ast_sip_report_failed_acl(task_data->endpoint, task_data->rdata, "registrar_invalid_contacts_provided");
		ast_log(LOG_WARNING, "Failed to validate contacts in REGISTER request from '%s'\n",
				ast_sorcery_object_get_id(task_data->endpoint));
		return PJ_TRUE;
	}

	if ((MAX(added - deleted, 0) + (!task_data->aor->remove_existing ? ao2_container_count(contacts) : 0)) > task_data->aor->max_contacts) {
		/* Enforce the maximum number of contacts */
		pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), task_data->rdata, 403, NULL, NULL, NULL);
		ast_sip_report_failed_acl(task_data->endpoint, task_data->rdata, "registrar_attempt_exceeds_maximum_configured_contacts");
		ast_log(LOG_WARNING, "Registration attempt from endpoint '%s' to AOR '%s' will exceed max contacts of %d\n",
				ast_sorcery_object_get_id(task_data->endpoint), ast_sorcery_object_get_id(task_data->aor), task_data->aor->max_contacts);
		return PJ_TRUE;
	}

	if (!(details.pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "Contact Comparison", 256, 256))) {
		pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), task_data->rdata, 500, NULL, NULL, NULL);
		return PJ_TRUE;
	}

	/* Iterate each provided Contact header and add, update, or delete */
	while ((contact_hdr = pjsip_msg_find_hdr(task_data->rdata->msg_info.msg, PJSIP_H_CONTACT, contact_hdr ? contact_hdr->next : NULL))) {
		int expiration;
		char contact_uri[PJSIP_MAX_URL_SIZE];
		RAII_VAR(struct ast_sip_contact *, contact, NULL, ao2_cleanup);

		if (contact_hdr->star) {
			/* A star means to unregister everything, so do so for the possible contacts */
			ao2_callback(contacts, OBJ_NODATA | OBJ_MULTIPLE, registrar_delete_contact, (void *)aor_name);
			break;
		}

		if (!PJSIP_URI_SCHEME_IS_SIP(contact_hdr->uri) && !PJSIP_URI_SCHEME_IS_SIPS(contact_hdr->uri)) {
			/* This registrar only currently supports sip: and sips: URI schemes */
			continue;
		}

		expiration = registrar_get_expiration(task_data->aor, contact_hdr, task_data->rdata);
		details.uri = pjsip_uri_get_uri(contact_hdr->uri);
		pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, details.uri, contact_uri, sizeof(contact_uri));

		if (!(contact = ao2_callback(contacts, OBJ_UNLINK, registrar_find_contact, &details))) {
			/* If they are actually trying to delete a contact that does not exist... be forgiving */
			if (!expiration) {
				ast_verb(3, "Attempted to remove non-existent contact '%s' from AOR '%s' by request\n",
					contact_uri, aor_name);
				continue;
			}

			ast_sip_location_add_contact(task_data->aor, contact_uri, ast_tvadd(ast_tvnow(), ast_samp2tv(expiration, 1)));
			ast_verb(3, "Added contact '%s' to AOR '%s' with expiration of %d seconds\n",
				contact_uri, aor_name, expiration);
			ast_test_suite_event_notify("AOR_CONTACT_ADDED",
					"Contact: %s\r\n"
					"AOR: %s\r\n"
					"Expiration: %d",
					contact_uri,
					aor_name,
					expiration);
		} else if (expiration) {
			RAII_VAR(struct ast_sip_contact *, updated, ast_sorcery_copy(ast_sip_get_sorcery(), contact), ao2_cleanup);
			updated->expiration_time = ast_tvadd(ast_tvnow(), ast_samp2tv(expiration, 1));
			updated->qualify_frequency = task_data->aor->qualify_frequency;
			updated->authenticate_qualify = task_data->aor->authenticate_qualify;

			ast_sip_location_update_contact(updated);
			ast_debug(3, "Refreshed contact '%s' on AOR '%s' with new expiration of %d seconds\n",
				contact_uri, aor_name, expiration);
			ast_test_suite_event_notify("AOR_CONTACT_REFRESHED",
					"Contact: %s\r\n"
					"AOR: %s\r\n"
					"Expiration: %d",
					contact_uri,
					aor_name,
					expiration);
		} else {
			ast_sip_location_delete_contact(contact);
			ast_verb(3, "Removed contact '%s' from AOR '%s' due to request\n", contact_uri, aor_name);
			ast_test_suite_event_notify("AOR_CONTACT_REMOVED",
					"Contact: %s\r\n"
					"AOR: %s",
					contact_uri,
					aor_name);
		}
	}

	pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), details.pool);

	/* If the AOR is configured to remove any existing contacts that have not been updated/added as a result of this REGISTER
	 * do so
	 */
	if (task_data->aor->remove_existing) {
		ao2_callback(contacts, OBJ_NODATA | OBJ_MULTIPLE, registrar_delete_contact, NULL);
	}

	/* Update the contacts as things will probably have changed */
	ao2_cleanup(contacts);
	contacts = ast_sip_location_retrieve_aor_contacts(task_data->aor);

	/* Send a response containing all of the contacts (including static) that are present on this AOR */
	if (pjsip_endpt_create_response(ast_sip_get_pjsip_endpoint(), task_data->rdata, 200, NULL, &tdata) != PJ_SUCCESS) {
		return PJ_TRUE;
	}

	/* Add the date header to the response, some UAs use this to set their date and time */
	registrar_add_date_header(tdata);

	ao2_callback(contacts, 0, registrar_add_contact, tdata);

	if (pjsip_get_response_addr(tdata->pool, task_data->rdata, &addr) == PJ_SUCCESS) {
		pjsip_endpt_send_response(ast_sip_get_pjsip_endpoint(), &addr, tdata, NULL, NULL);
	} else {
		pjsip_tx_data_dec_ref(tdata);
	}

	return PJ_TRUE;
}
Exemple #23
0
/* This is called when request is received. 
 * We need to check for incoming SUBSCRIBE request.
 */
static pj_bool_t pres_on_rx_request(pjsip_rx_data *rdata)
{
    int acc_id;
    pjsua_acc *acc;
    pj_str_t contact;
    pjsip_method *req_method = &rdata->msg_info.msg->line.req.method;
    pjsua_srv_pres *uapres;
    pjsip_evsub *sub;
    pjsip_evsub_user pres_cb;
    pjsip_dialog *dlg;
    pjsip_status_code st_code;
    pj_str_t reason;
    pjsip_expires_hdr *expires_hdr;
    pjsua_msg_data msg_data;
    pj_status_t status;

    if (pjsip_method_cmp(req_method, pjsip_get_subscribe_method()) != 0)
	return PJ_FALSE;

    /* Incoming SUBSCRIBE: */

    PJSUA_LOCK();

    /* Find which account for the incoming request. */
    acc_id = pjsua_acc_find_for_incoming(rdata);
    acc = &pjsua_var.acc[acc_id];

    PJ_LOG(4,(THIS_FILE, "Creating server subscription, using account %d",
	      acc_id));
    
    /* Create suitable Contact header */
    if (acc->contact.slen) {
	contact = acc->contact;
    } else {
	status = pjsua_acc_create_uas_contact(rdata->tp_info.pool, &contact,
					      acc_id, rdata);
	if (status != PJ_SUCCESS) {
	    pjsua_perror(THIS_FILE, "Unable to generate Contact header", 
			 status);
	    PJSUA_UNLOCK();
	    pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 400, NULL,
					  NULL, NULL);
	    return PJ_TRUE;
	}
    }

    /* Create UAS dialog: */
    status = pjsip_dlg_create_uas(pjsip_ua_instance(), rdata, 
				  &contact, &dlg);
    if (status != PJ_SUCCESS) {
	pjsua_perror(THIS_FILE, 
		     "Unable to create UAS dialog for subscription", 
		     status);
	PJSUA_UNLOCK();
	pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 400, NULL,
				      NULL, NULL);
	return PJ_TRUE;
    }

    /* Set credentials and preference. */
    pjsip_auth_clt_set_credentials(&dlg->auth_sess, acc->cred_cnt, acc->cred);
    pjsip_auth_clt_set_prefs(&dlg->auth_sess, &acc->cfg.auth_pref);

    /* Init callback: */
    pj_bzero(&pres_cb, sizeof(pres_cb));
    pres_cb.on_evsub_state = &pres_evsub_on_srv_state;

    /* Create server presence subscription: */
    status = pjsip_pres_create_uas( dlg, &pres_cb, rdata, &sub);
    if (status != PJ_SUCCESS) {
	int code = PJSIP_ERRNO_TO_SIP_STATUS(status);
	pjsip_tx_data *tdata;

	pjsua_perror(THIS_FILE, "Unable to create server subscription", 
		     status);

	if (code==599 || code > 699 || code < 300) {
	    code = 400;
	}

	status = pjsip_dlg_create_response(dlg, rdata, code, NULL, &tdata);
	if (status == PJ_SUCCESS) {
	    status = pjsip_dlg_send_response(dlg, pjsip_rdata_get_tsx(rdata),
					     tdata);
	}

	PJSUA_UNLOCK();
	return PJ_TRUE;
    }

    /* If account is locked to specific transport, then lock dialog
     * to this transport too.
     */
    if (acc->cfg.transport_id != PJSUA_INVALID_ID) {
	pjsip_tpselector tp_sel;

	pjsua_init_tpselector(acc->cfg.transport_id, &tp_sel);
	pjsip_dlg_set_transport(dlg, &tp_sel);
    }

    /* Attach our data to the subscription: */
    uapres = PJ_POOL_ALLOC_T(dlg->pool, pjsua_srv_pres);
    uapres->sub = sub;
    uapres->remote = (char*) pj_pool_alloc(dlg->pool, PJSIP_MAX_URL_SIZE);
    uapres->acc_id = acc_id;
    uapres->dlg = dlg;
    status = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, dlg->remote.info->uri,
			     uapres->remote, PJSIP_MAX_URL_SIZE);
    if (status < 1)
	pj_ansi_strcpy(uapres->remote, "<-- url is too long-->");
    else
	uapres->remote[status] = '\0';

    pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, uapres);

    /* Add server subscription to the list: */
    pj_list_push_back(&pjsua_var.acc[acc_id].pres_srv_list, uapres);


    /* Capture the value of Expires header. */
    expires_hdr = (pjsip_expires_hdr*)
    		  pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES,
				     NULL);
    if (expires_hdr)
	uapres->expires = expires_hdr->ivalue;
    else
	uapres->expires = -1;

    st_code = (pjsip_status_code)200;
    reason = pj_str("OK");
    pjsua_msg_data_init(&msg_data);

    /* Notify application callback, if any */
    if (pjsua_var.ua_cfg.cb.on_incoming_subscribe) {
	pjsua_buddy_id buddy_id;

	buddy_id = pjsua_find_buddy(rdata->msg_info.from->uri);

	(*pjsua_var.ua_cfg.cb.on_incoming_subscribe)(acc_id, uapres, buddy_id,
						     &dlg->remote.info_str, 
						     rdata, &st_code, &reason,
						     &msg_data);
    }

    /* Handle rejection case */
    if (st_code >= 300) {
	pjsip_tx_data *tdata;

	/* Create response */
	status = pjsip_dlg_create_response(dlg, rdata, st_code, 
					   &reason, &tdata);
	if (status != PJ_SUCCESS) {
	    pjsua_perror(THIS_FILE, "Error creating response",  status);
	    pj_list_erase(uapres);
	    pjsip_pres_terminate(sub, PJ_FALSE);
	    PJSUA_UNLOCK();
	    return PJ_FALSE;
	}

	/* Add header list, if any */
	pjsua_process_msg_data(tdata, &msg_data);

	/* Send the response */
	status = pjsip_dlg_send_response(dlg, pjsip_rdata_get_tsx(rdata),
					 tdata);
	if (status != PJ_SUCCESS) {
	    pjsua_perror(THIS_FILE, "Error sending response",  status);
	    /* This is not fatal */
	}

	/* Terminate presence subscription */
	pj_list_erase(uapres);
	pjsip_pres_terminate(sub, PJ_FALSE);
	PJSUA_UNLOCK();
	return PJ_TRUE;
    }

    /* Create and send 2xx response to the SUBSCRIBE request: */
    status = pjsip_pres_accept(sub, rdata, st_code, &msg_data.hdr_list);
    if (status != PJ_SUCCESS) {
	pjsua_perror(THIS_FILE, "Unable to accept presence subscription", 
		     status);
	pj_list_erase(uapres);
	pjsip_pres_terminate(sub, PJ_FALSE);
	PJSUA_UNLOCK();
	return PJ_FALSE;
    }

    /* If code is 200, send NOTIFY now */
    if (st_code == 200) {
	pjsua_pres_notify(acc_id, uapres, PJSIP_EVSUB_STATE_ACTIVE, 
			  NULL, NULL, PJ_TRUE, &msg_data);
    }

    /* Done: */

    PJSUA_UNLOCK();

    return PJ_TRUE;
}
Exemple #24
0
/*
 * Callback when incoming requests outside any transactions and any
 * dialogs are received. We're only interested to hande incoming INVITE
 * request, and we'll reject any other requests with 500 response.
 */
static pj_bool_t on_rx_request( pjsip_rx_data *rdata )
{
    pj_sockaddr hostaddr;
    char temp[80], hostip[PJ_INET6_ADDRSTRLEN];
    pj_str_t local_uri;
    pjsip_dialog *dlg;
    pjmedia_sdp_session *local_sdp;
    pjsip_tx_data *tdata;
    unsigned options = 0;
    pj_status_t status;


    /* 
     * Respond (statelessly) any non-INVITE requests with 500 
     */
    if (rdata->msg_info.msg->line.req.method.id != PJSIP_INVITE_METHOD) {

	if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) {
	    pj_str_t reason = pj_str("Simple UA unable to handle "
				     "this request");

	    pjsip_endpt_respond_stateless( g_endpt, rdata, 
					   500, &reason,
					   NULL, NULL);
	}
	return PJ_TRUE;
    }


    /*
     * Reject INVITE if we already have an INVITE session in progress.
     */
    if (g_inv) {

	pj_str_t reason = pj_str("Another call is in progress");

	pjsip_endpt_respond_stateless( g_endpt, rdata, 
				       500, &reason,
				       NULL, NULL);
	return PJ_TRUE;

    }

    /* Verify that we can handle the request. */
    status = pjsip_inv_verify_request(rdata, &options, NULL, NULL,
				      g_endpt, NULL);
    if (status != PJ_SUCCESS) {

	pj_str_t reason = pj_str("Sorry Simple UA can not handle this INVITE");

	pjsip_endpt_respond_stateless( g_endpt, rdata, 
				       500, &reason,
				       NULL, NULL);
	return PJ_TRUE;
    } 

    /*
     * Generate Contact URI
     */
    if (pj_gethostip(AF, &hostaddr) != PJ_SUCCESS) {
	app_perror(THIS_FILE, "Unable to retrieve local host IP", status);
	return PJ_TRUE;
    }
    pj_sockaddr_print(&hostaddr, hostip, sizeof(hostip), 2);

    pj_ansi_sprintf(temp, "<sip:simpleuas@%s:%d>", 
		    hostip, SIP_PORT);
    local_uri = pj_str(temp);

    /*
     * Create UAS dialog.
     */
    status = pjsip_dlg_create_uas( pjsip_ua_instance(), 
				   rdata,
				   &local_uri, /* contact */
				   &dlg);
    if (status != PJ_SUCCESS) {
	pjsip_endpt_respond_stateless(g_endpt, rdata, 500, NULL,
				      NULL, NULL);
	return PJ_TRUE;
    }

    /* 
     * Get media capability from media endpoint: 
     */

    status = pjmedia_endpt_create_sdp( g_med_endpt, rdata->tp_info.pool,
				       MAX_MEDIA_CNT, g_sock_info, &local_sdp);
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);


    /* 
     * Create invite session, and pass both the UAS dialog and the SDP
     * capability to the session.
     */
    status = pjsip_inv_create_uas( dlg, rdata, local_sdp, 0, &g_inv);
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);


    /*
     * Initially send 180 response.
     *
     * The very first response to an INVITE must be created with
     * pjsip_inv_initial_answer(). Subsequent responses to the same
     * transaction MUST use pjsip_inv_answer().
     */
    status = pjsip_inv_initial_answer(g_inv, rdata, 
				      180, 
				      NULL, NULL, &tdata);
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);


    /* Send the 180 response. */  
    status = pjsip_inv_send_msg(g_inv, tdata); 
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);


    /*
     * Now create 200 response.
     */
    status = pjsip_inv_answer( g_inv, 
			       200, NULL,	/* st_code and st_text */
			       NULL,		/* SDP already specified */
			       &tdata);
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);

    /*
     * Send the 200 response.
     */
    status = pjsip_inv_send_msg(g_inv, tdata);
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);


    /* Done. 
     * When the call is disconnected, it will be reported via the callback.
     */

    return PJ_TRUE;
}
Exemple #25
0
/*
 * Handler to receive incoming MESSAGE
 */
static pj_bool_t im_on_rx_request(pjsip_rx_data *rdata)
{
    pj_str_t from, to;
    pjsip_accept_hdr *accept_hdr;
    pjsip_msg *msg;

    msg = rdata->msg_info.msg;

    /* Only want to handle MESSAGE requests. */
    if (pjsip_method_cmp(&msg->line.req.method, &pjsip_message_method) != 0) {
	return PJ_FALSE;
    }


    /* Should not have any transaction attached to rdata. */
    PJ_ASSERT_RETURN(pjsip_rdata_get_tsx(rdata)==NULL, PJ_FALSE);

    /* Should not have any dialog attached to rdata. */
    PJ_ASSERT_RETURN(pjsip_rdata_get_dlg(rdata)==NULL, PJ_FALSE);

    /* Check if we can accept the message. */
    if (!pjsua_im_accept_pager(rdata, &accept_hdr)) {
	pjsip_hdr hdr_list;

	pj_list_init(&hdr_list);
	pj_list_push_back(&hdr_list, accept_hdr);

	pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 
				      PJSIP_SC_NOT_ACCEPTABLE_HERE, NULL, 
				      &hdr_list, NULL);
	return PJ_TRUE;
    }
    
    /* Respond with 200 first, so that remote doesn't retransmit in case
     * the UI takes too long to process the message. 
     */
    pjsip_endpt_respond( pjsua_var.endpt, NULL, rdata, 200, NULL,
			 NULL, NULL, NULL);

    /* For the source URI, we use Contact header if present, since
     * Contact header contains the port number information. If this is
     * not available, then use From header.
     */
    from.ptr = (char*)pj_pool_alloc(rdata->tp_info.pool, PJSIP_MAX_URL_SIZE);
    from.slen = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, 
				rdata->msg_info.from->uri,
				from.ptr, PJSIP_MAX_URL_SIZE);

    if (from.slen < 1)
	from = pj_str("<--URI is too long-->");

    /* Build the To text. */
    to.ptr = (char*) pj_pool_alloc(rdata->tp_info.pool, PJSIP_MAX_URL_SIZE);
    to.slen = pjsip_uri_print( PJSIP_URI_IN_FROMTO_HDR, 
			       rdata->msg_info.to->uri,
			       to.ptr, PJSIP_MAX_URL_SIZE);
    if (to.slen < 1)
	to = pj_str("<--URI is too long-->");

    /* Process pager. */
    pjsua_im_process_pager(-1, &from, &to, rdata);

    /* Done. */
    return PJ_TRUE;
}
Exemple #26
0
/* Proxy utility to verify incoming requests.
 * Return non-zero if verification failed.
 */
static pj_status_t proxy_verify_request(pjsip_rx_data *rdata)
{
    const pj_str_t STR_PROXY_REQUIRE = {"Proxy-Require", 13};

    /* RFC 3261 Section 16.3 Request Validation */

    /* Before an element can proxy a request, it MUST verify the message's
     * validity.  A valid message must pass the following checks:
     *
     * 1. Reasonable Syntax
     * 2. URI scheme
     * 3. Max-Forwards
     * 4. (Optional) Loop Detection
     * 5. Proxy-Require
     * 6. Proxy-Authorization
     */

    /* 1. Reasonable Syntax.
     * This would have been checked by transport layer.
     */

    /* 2. URI scheme.
     * We only want to support "sip:" URI scheme for this simple proxy.
     */
    if (!PJSIP_URI_SCHEME_IS_SIP(rdata->msg_info.msg->line.req.uri)) {
        pjsip_endpt_respond_stateless(global.endpt, rdata,
                                      PJSIP_SC_UNSUPPORTED_URI_SCHEME, NULL,
                                      NULL, NULL);
        return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_UNSUPPORTED_URI_SCHEME);
    }

    /* 3. Max-Forwards.
     * Send error if Max-Forwards is 1 or lower.
     */
    if (rdata->msg_info.max_fwd && rdata->msg_info.max_fwd->ivalue <= 1) {
        pjsip_endpt_respond_stateless(global.endpt, rdata,
                                      PJSIP_SC_TOO_MANY_HOPS, NULL,
                                      NULL, NULL);
        return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_TOO_MANY_HOPS);
    }

    /* 4. (Optional) Loop Detection.
     * Nah, we don't do that with this simple proxy.
     */

    /* 5. Proxy-Require */
    if (pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &STR_PROXY_REQUIRE,
                                   NULL) != NULL)
    {
        pjsip_endpt_respond_stateless(global.endpt, rdata,
                                      PJSIP_SC_BAD_EXTENSION, NULL,
                                      NULL, NULL);
        return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_BAD_EXTENSION);
    }

    /* 6. Proxy-Authorization.
     * Nah, we don't require any authorization with this sample.
     */

    return PJ_SUCCESS;
}
Exemple #27
-1
int dummy_function()
{
    pj_caching_pool cp;
 
    sprintf(NULL, "%d", 0);
    rand();
    
#ifdef HAS_PJLIB
    pj_init();
    pj_caching_pool_init(&cp, NULL, 0);
    pj_array_erase(NULL, 0, 0, 0);
    pj_create_unique_string(NULL, NULL);
    pj_hash_create(NULL, 0);
    pj_hash_get(NULL, NULL, 0, NULL);
    pj_hash_set(NULL, NULL, NULL, 0, 0, NULL);
    pj_ioqueue_create(NULL, 0, NULL);
    pj_ioqueue_register_sock(NULL, NULL, 0, NULL, NULL, NULL);
    pj_pool_alloc(NULL, 0);
    pj_timer_heap_create(NULL, 0, NULL);
#endif

#ifdef HAS_PJLIB_STUN
    pjstun_get_mapped_addr(&cp.factory, 0, NULL, NULL, 80, NULL, 80, NULL);
#endif

#ifdef HAS_PJLIB_GETOPT
    pj_getopt_long(0, NULL, NULL, NULL, NULL);
#endif
    
#ifdef HAS_PJLIB_XML
    pj_xml_parse(NULL, NULL, 100);
    pj_xml_print(NULL, NULL, 10, PJ_FALSE);
    pj_xml_clone(NULL, NULL);
    pj_xml_node_new(NULL, NULL);
    pj_xml_attr_new(NULL, NULL, NULL);
    pj_xml_add_node(NULL, NULL);
    pj_xml_add_attr(NULL, NULL);
    pj_xml_find_node(NULL, NULL);
    pj_xml_find_next_node(NULL, NULL, NULL);
    pj_xml_find_attr(NULL, NULL, NULL);
    pj_xml_find(NULL, NULL, NULL, NULL);
#endif

#ifdef HAS_PJLIB_SCANNER
    pj_cis_buf_init(NULL);
    pj_cis_init(NULL, NULL);
    pj_cis_dup(NULL, NULL);
    pj_cis_add_alpha(NULL);
    pj_cis_add_str(NULL, NULL);

    pj_scan_init(NULL, NULL, 0, 0, NULL);
    pj_scan_fini(NULL);
    pj_scan_peek(NULL, NULL, NULL);
    pj_scan_peek_n(NULL, 0, NULL);
    pj_scan_peek_until(NULL, NULL, NULL);
    pj_scan_get(NULL, NULL, NULL);
    pj_scan_get_unescape(NULL, NULL, NULL);
    pj_scan_get_quote(NULL, 0, 0, NULL);
    pj_scan_get_n(NULL, 0, NULL);
    pj_scan_get_char(NULL);
    pj_scan_get_until(NULL, NULL, NULL);
    pj_scan_strcmp(NULL, NULL, 0);
    pj_scan_stricmp(NULL, NULL, 0);
    pj_scan_stricmp_alnum(NULL, NULL, 0);
    pj_scan_get_newline(NULL);
    pj_scan_restore_state(NULL, NULL);
#endif

#ifdef HAS_PJLIB_DNS
    pj_dns_make_query(NULL, NULL, 0, 0, NULL);
    pj_dns_parse_packet(NULL, NULL, 0, NULL);
    pj_dns_packet_dup(NULL, NULL, 0, NULL);
#endif

#ifdef HAS_PJLIB_RESOLVER
    pj_dns_resolver_create(NULL, NULL, 0, NULL, NULL, NULL);
    pj_dns_resolver_set_ns(NULL, 0, NULL, NULL);
    pj_dns_resolver_handle_events(NULL, NULL);
    pj_dns_resolver_destroy(NULL, 0);
    pj_dns_resolver_start_query(NULL, NULL, 0, 0, NULL, NULL, NULL);
    pj_dns_resolver_cancel_query(NULL, 0);
    pj_dns_resolver_add_entry(NULL, NULL, 0);
#endif

#ifdef HAS_PJLIB_SRV_RESOLVER
    pj_dns_srv_resolve(NULL, NULL, 0, NULL, NULL, PJ_FALSE, NULL, NULL);
#endif

#ifdef HAS_PJLIB_CRC32
    pj_crc32_init(NULL);
    pj_crc32_update(NULL, NULL, 0);
    pj_crc32_final(NULL);
#endif

#ifdef HAS_PJLIB_HMAC_MD5
    pj_hmac_md5(NULL, 0, NULL, 0, NULL);
#endif

#ifdef HAS_PJLIB_HMAC_SHA1
    pj_hmac_sha1(NULL, 0, NULL, 0, NULL);
#endif

#ifdef HAS_PJNATH_STUN
    pj_stun_session_create(NULL, NULL, NULL, PJ_FALSE, NULL);
    pj_stun_session_destroy(NULL);
    pj_stun_session_set_credential(NULL, NULL);
    pj_stun_session_create_req(NULL, 0, NULL, NULL);
    pj_stun_session_create_ind(NULL, 0, NULL);
    pj_stun_session_create_res(NULL, NULL, 0, NULL, NULL);
    pj_stun_session_send_msg(NULL, PJ_FALSE, NULL, 0, NULL);
#endif

#ifdef HAS_PJNATH_ICE
    pj_ice_strans_create(NULL, NULL, 0, NULL, NULL, NULL);
    pj_ice_strans_set_stun_domain(NULL, NULL, NULL);
    pj_ice_strans_create_comp(NULL, 0, 0, NULL);
    pj_ice_strans_add_cand(NULL, 0, PJ_ICE_CAND_TYPE_HOST, 0, NULL, PJ_FALSE);
    pj_ice_strans_init_ice(NULL, PJ_ICE_SESS_ROLE_CONTROLLED, NULL, NULL);
    pj_ice_strans_start_ice(NULL, NULL, NULL, 0, NULL);
    pj_ice_strans_stop_ice(NULL);
    pj_ice_strans_sendto(NULL, 0, NULL, 0, NULL, 0);
#endif

#ifdef HAS_PJSIP_CORE_MSG_ELEM
    /* Parameter container */
    pjsip_param_find(NULL, NULL);
    pjsip_param_print_on(NULL, NULL, 0, NULL, NULL, 0);

    /* SIP URI */
    pjsip_sip_uri_create(NULL, 0);
    pjsip_name_addr_create(NULL);

    /* TEL URI */
    pjsip_tel_uri_create(NULL);

    /* Message and headers */
    pjsip_msg_create(NULL, PJSIP_REQUEST_MSG);
    pjsip_msg_print(NULL, NULL, 0);
    pjsip_accept_hdr_create(NULL);
    pjsip_allow_hdr_create(NULL);
    pjsip_cid_hdr_create(NULL);
    pjsip_clen_hdr_create(NULL);
    pjsip_cseq_hdr_create(NULL);
    pjsip_contact_hdr_create(NULL);
    pjsip_ctype_hdr_create(NULL);
    pjsip_expires_hdr_create(NULL, 0);
    pjsip_from_hdr_create(NULL);
    pjsip_max_fwd_hdr_create(NULL, 0);
    pjsip_min_expires_hdr_create(NULL, 0);
    pjsip_rr_hdr_create(NULL);
    pjsip_require_hdr_create(NULL);
    pjsip_retry_after_hdr_create(NULL, 0);
    pjsip_supported_hdr_create(NULL);
    pjsip_unsupported_hdr_create(NULL);
    pjsip_via_hdr_create(NULL);
    pjsip_warning_hdr_create(NULL, 0, NULL, NULL);

    pjsip_parse_uri(NULL, NULL, 0, 0);
    pjsip_parse_msg(NULL, NULL, 0, NULL);
    pjsip_parse_rdata(NULL, 0, NULL);
    pjsip_find_msg(NULL, 0, 0, NULL);
#endif

#ifdef HAS_PJSIP_CORE
    pjsip_endpt_create(NULL, NULL, NULL);

    pjsip_tpmgr_create(NULL, NULL, NULL, NULL, NULL);
    pjsip_tpmgr_destroy(NULL);
    pjsip_transport_send(NULL, NULL, NULL, 0, NULL, NULL);


#endif

#ifdef HAS_PJSIP_CORE_MSG_UTIL
    pjsip_endpt_create_request(NULL, NULL, NULL, NULL, NULL, NULL, NULL,
			       -1, NULL, NULL);
    pjsip_endpt_create_request_from_hdr(NULL, NULL, NULL, NULL, NULL, NULL,
					NULL, -1, NULL, NULL);
    pjsip_endpt_create_response(NULL, NULL, -1, NULL, NULL);
    pjsip_endpt_create_ack(NULL, NULL, NULL, NULL);
    pjsip_endpt_create_cancel(NULL, NULL, NULL);
    pjsip_get_request_dest(NULL, NULL);
    pjsip_endpt_send_request_stateless(NULL, NULL, NULL, NULL);
    pjsip_get_response_addr(NULL, NULL, NULL);
    pjsip_endpt_send_response(NULL, NULL, NULL, NULL, NULL);
    pjsip_endpt_respond_stateless(NULL, NULL, -1, NULL, NULL, NULL);
#endif

#ifdef HAS_PJSIP_UDP_TRANSPORT
    pjsip_udp_transport_start(NULL, NULL, NULL, 1, NULL);
#endif

#ifdef HAS_PJSIP_TCP_TRANSPORT
    pjsip_tcp_transport_start(NULL, NULL, 1, NULL);
#endif

#ifdef HAS_PJSIP_TLS_TRANSPORT
    pjsip_tls_transport_start(NULL, NULL, NULL, NULL, 0, NULL);
#endif

#ifdef HAS_PJSIP_TRANSACTION
    pjsip_tsx_layer_init_module(NULL);

    pjsip_tsx_layer_destroy();
    pjsip_tsx_create_uac(NULL, NULL, NULL);
    pjsip_tsx_create_uas(NULL, NULL, NULL);
    pjsip_tsx_recv_msg(NULL, NULL);
    pjsip_tsx_send_msg(NULL, NULL);
    pjsip_tsx_terminate(NULL, 200);

    pjsip_endpt_send_request(NULL, NULL, -1, NULL, NULL);
    pjsip_endpt_respond(NULL, NULL, NULL, -1, NULL, NULL, NULL, NULL);
#endif

#ifdef HAS_PJMEDIA_SDP
    pjmedia_sdp_parse(NULL, NULL, 1024, NULL);
    pjmedia_sdp_print(NULL, NULL, 1024);
    pjmedia_sdp_validate(NULL);
    pjmedia_sdp_session_clone(NULL, NULL);
    pjmedia_sdp_session_cmp(NULL, NULL, 0);
    pjmedia_sdp_attr_to_rtpmap(NULL, NULL, NULL);
    pjmedia_sdp_attr_get_fmtp(NULL, NULL);
    pjmedia_sdp_attr_get_rtcp(NULL, NULL);
    pjmedia_sdp_conn_clone(NULL, NULL);
    pjmedia_sdp_media_clone(NULL, NULL);
    pjmedia_sdp_media_find_attr(NULL, NULL, NULL);
#endif

#ifdef HAS_PJMEDIA_SDP_NEGOTIATOR
    pjmedia_sdp_neg_create_w_local_offer(NULL, NULL, NULL);
    pjmedia_sdp_neg_create_w_remote_offer(NULL, NULL, NULL, NULL);
    pjmedia_sdp_neg_get_state(NULL);
    pjmedia_sdp_neg_negotiate(NULL, NULL, PJ_FALSE);
#endif

#ifdef HAS_PJSIP_UA_LAYER
    pjsip_ua_init_module(NULL, NULL);
    pjsip_ua_destroy();
    pjsip_dlg_create_uac(NULL, NULL, NULL, NULL, NULL, NULL);
    pjsip_dlg_create_uas_and_inc_lock(NULL, NULL, NULL, NULL);
    pjsip_dlg_terminate(NULL);
    pjsip_dlg_set_route_set(NULL, NULL);
    pjsip_dlg_create_request(NULL, NULL, -1, NULL);
    pjsip_dlg_send_request(NULL, NULL, -1, NULL);
    pjsip_dlg_create_response(NULL, NULL, -1, NULL, NULL);
    pjsip_dlg_modify_response(NULL, NULL, -1, NULL);
    pjsip_dlg_send_response(NULL, NULL, NULL);
    pjsip_dlg_respond(NULL, NULL, -1, NULL, NULL, NULL);
#endif

#ifdef HAS_PJSIP_AUTH_CLIENT
    pjsip_auth_clt_init(NULL, NULL, NULL, 0);
    pjsip_auth_clt_clone(NULL, NULL, NULL);
    pjsip_auth_clt_set_credentials(NULL, 0, NULL);
    pjsip_auth_clt_init_req(NULL, NULL);
    pjsip_auth_clt_reinit_req(NULL, NULL, NULL, NULL);
#endif

#ifdef HAS_PJSIP_INV_SESSION
    pjsip_inv_usage_init(NULL, NULL);
    pjsip_inv_create_uac(NULL, NULL, 0, NULL);
    pjsip_inv_verify_request(NULL, NULL, NULL, NULL, NULL, NULL);
    pjsip_inv_create_uas(NULL, NULL, NULL, 0, NULL);
    pjsip_inv_terminate(NULL, 200, PJ_FALSE);
    pjsip_inv_invite(NULL, NULL);
    pjsip_inv_initial_answer(NULL, NULL, 200, NULL, NULL, NULL);
    pjsip_inv_answer(NULL, 200, NULL, NULL, NULL);
    pjsip_inv_end_session(NULL, 200, NULL, NULL);
    pjsip_inv_reinvite(NULL, NULL, NULL, NULL);
    pjsip_inv_update(NULL, NULL, NULL, NULL);
    pjsip_inv_send_msg(NULL, NULL);
    pjsip_dlg_get_inv_session(NULL);
    //pjsip_tsx_get_inv_session(NULL);
    pjsip_inv_state_name(PJSIP_INV_STATE_NULL);
#endif

#ifdef HAS_PJSIP_REGC
    //pjsip_regc_get_module();
    pjsip_regc_create(NULL, NULL, NULL, NULL);
    pjsip_regc_destroy(NULL);
    pjsip_regc_get_info(NULL, NULL);
    pjsip_regc_get_pool(NULL);
    pjsip_regc_init(NULL, NULL, NULL, NULL, 0, NULL, 600);
    pjsip_regc_set_credentials(NULL, 1, NULL);
    pjsip_regc_set_route_set(NULL, NULL);
    pjsip_regc_register(NULL, PJ_TRUE, NULL);
    pjsip_regc_unregister(NULL, NULL);
    pjsip_regc_update_contact(NULL, 10, NULL);
    pjsip_regc_update_expires(NULL, 600);
    pjsip_regc_send(NULL, NULL);
#endif

#ifdef HAS_PJSIP_EVENT_FRAMEWORK
    pjsip_evsub_init_module(NULL);
    pjsip_evsub_instance();
    pjsip_evsub_register_pkg(NULL, NULL, 30, 10, NULL);
    pjsip_evsub_create_uac(NULL, NULL, NULL, 10, NULL);
    pjsip_evsub_create_uas(NULL, NULL, NULL, 10, NULL);
    pjsip_evsub_terminate(NULL, PJ_FALSE);
    pjsip_evsub_get_state(NULL);
    pjsip_evsub_get_state_name(NULL);
    pjsip_evsub_initiate(NULL, NULL, -1, NULL);
    pjsip_evsub_accept(NULL, NULL, 200, NULL);
    pjsip_evsub_notify(NULL, PJSIP_EVSUB_STATE_ACTIVE, NULL, NULL, NULL);
    pjsip_evsub_current_notify(NULL, NULL);
    pjsip_evsub_send_request(NULL, NULL);
    pjsip_tsx_get_evsub(NULL);
    pjsip_evsub_set_mod_data(NULL, 1, NULL);
    pjsip_evsub_get_mod_data(NULL, 1);
#endif

#ifdef HAS_PJSIP_CALL_TRANSFER
    pjsip_xfer_init_module(NULL);
    pjsip_xfer_create_uac(NULL, NULL, NULL);
    pjsip_xfer_create_uas(NULL, NULL, NULL, NULL);
    pjsip_xfer_initiate(NULL, NULL, NULL);
    pjsip_xfer_accept(NULL, NULL, 200, NULL);
    pjsip_xfer_notify(NULL, PJSIP_EVSUB_STATE_ACTIVE, 200, NULL, NULL);
    pjsip_xfer_current_notify(NULL, NULL);
    pjsip_xfer_send_request(NULL, NULL);
#endif

#ifdef HAS_PJSIP_PRESENCE
    pjsip_pres_init_module(NULL, NULL);
    pjsip_pres_instance();
    pjsip_pres_create_uac(NULL, NULL, 0, NULL);
    pjsip_pres_create_uas(NULL, NULL, NULL, NULL);
    pjsip_pres_terminate(NULL, PJ_FALSE);
    pjsip_pres_initiate(NULL, 100, NULL);
    pjsip_pres_accept(NULL, NULL, 200, NULL);
    pjsip_pres_notify(NULL, PJSIP_EVSUB_STATE_ACTIVE, NULL, NULL, NULL);
    pjsip_pres_current_notify(NULL, NULL);
    pjsip_pres_send_request(NULL, NULL);
    pjsip_pres_get_status(NULL, NULL);
    pjsip_pres_set_status(NULL, NULL);
#endif

#ifdef HAS_PJSIP_IS_COMPOSING
    pjsip_iscomposing_create_xml(NULL, PJ_TRUE, NULL, NULL, 0);
    pjsip_iscomposing_create_body(NULL, PJ_TRUE, NULL, NULL, 0);
    pjsip_iscomposing_parse(NULL, NULL, 0, NULL, NULL, NULL, NULL);
#endif

#ifdef HAS_PJMEDIA
    pjmedia_endpt_create(NULL, NULL, 1, NULL);
    pjmedia_endpt_destroy(NULL);
    pjmedia_endpt_create_sdp(NULL, NULL, 1, NULL, NULL);
#endif

#ifdef HAS_PJMEDIA_EC
    pjmedia_echo_create(NULL, 0, 0, 0, 0, 0, NULL);
    pjmedia_echo_destroy(NULL);
    pjmedia_echo_playback(NULL, NULL);
    pjmedia_echo_capture(NULL, NULL, 0);
    pjmedia_echo_cancel(NULL, NULL, NULL, 0, NULL);
#endif

#ifdef HAS_PJMEDIA_SND_DEV
    pjmedia_snd_init(NULL);
    pjmedia_snd_get_dev_count();
    pjmedia_snd_get_dev_info(0);
    pjmedia_snd_open(-1, -1, 8000, 1, 80, 16, NULL, NULL, NULL, NULL);
    pjmedia_snd_open_rec(-1, 8000, 1, 160, 16, NULL, NULL, NULL);
    pjmedia_snd_open_player(-1, 8000, 1, 160, 16, NULL, NULL, NULL);
    pjmedia_snd_stream_start(NULL);
    pjmedia_snd_stream_stop(NULL);
    pjmedia_snd_stream_close(NULL);
    pjmedia_snd_deinit();
#endif

#ifdef HAS_PJMEDIA_SND_PORT
    pjmedia_snd_port_create(NULL, -1, -1, 8000, 1, 180, 16, 0, NULL);
    pjmedia_snd_port_create_rec(NULL, -1, 8000, 1, 160, 16, 0, NULL);
    pjmedia_snd_port_create_player(NULL, -1, 8000, 1, 160, 16, 0, NULL);
    pjmedia_snd_port_destroy(NULL);
    pjmedia_snd_port_get_snd_stream(NULL);
    pjmedia_snd_port_connect(NULL, NULL);
    pjmedia_snd_port_get_port(NULL);
    pjmedia_snd_port_disconnect(NULL);
#endif

#ifdef HAS_PJMEDIA_RESAMPLE
    pjmedia_resample_create(NULL, PJ_TRUE, PJ_TRUE, 0, 0, 0, 0, NULL);
    pjmedia_resample_run(NULL, NULL, NULL);
#endif

#ifdef HAS_PJMEDIA_SILENCE_DET
    pjmedia_silence_det_create(NULL, 8000, 80, NULL);
    pjmedia_silence_det_detect(NULL, NULL, 0, NULL);
    pjmedia_silence_det_apply(NULL, 0);
#endif

#ifdef HAS_PJMEDIA_PLC
    pjmedia_plc_create(NULL, 8000, 80, 0, NULL);
    pjmedia_plc_save(NULL, NULL);
    pjmedia_plc_generate(NULL, NULL);
#endif

#ifdef HAS_PJMEDIA_CONFERENCE
    pjmedia_conf_create(NULL, 10, 8000, 1, 160, 16, 0, NULL);
    pjmedia_conf_destroy(NULL);
    pjmedia_conf_get_master_port(NULL);
    pjmedia_conf_add_port(NULL, NULL, NULL, NULL, NULL);
    pjmedia_conf_configure_port(NULL, 1, 0, 0);
    pjmedia_conf_connect_port(NULL, 0, 0, 0);
    pjmedia_conf_disconnect_port(NULL, 0, 0);
    pjmedia_conf_remove_port(NULL, 0);
    pjmedia_conf_enum_ports(NULL, NULL, NULL);
    pjmedia_conf_get_port_info(NULL, 0, NULL);
    pjmedia_conf_get_ports_info(NULL, NULL, NULL);
    pjmedia_conf_get_signal_level(NULL, 0, NULL, NULL);
    pjmedia_conf_adjust_rx_level(NULL, 0, 0);
    pjmedia_conf_adjust_tx_level(NULL, 0, 0);
#endif

#ifdef HAS_PJMEDIA_MASTER_PORT
    pjmedia_master_port_create(NULL, NULL, NULL, 0, NULL);
    pjmedia_master_port_start(NULL);
    pjmedia_master_port_stop(NULL);
    pjmedia_master_port_set_uport(NULL, NULL);
    pjmedia_master_port_get_uport(NULL);
    pjmedia_master_port_set_dport(NULL, NULL);
    pjmedia_master_port_get_dport(NULL);
    pjmedia_master_port_destroy(NULL, PJ_FALSE);
#endif

#ifdef HAS_PJMEDIA_RTP
    pjmedia_rtp_session_init(NULL, 0, 0);
    pjmedia_rtp_encode_rtp(NULL, 0, 0, 0, 0, NULL, NULL);
    pjmedia_rtp_decode_rtp(NULL, NULL, 0, NULL, NULL, NULL);
    pjmedia_rtp_session_update(NULL, NULL, NULL);
#endif

#ifdef HAS_PJMEDIA_RTCP
    pjmedia_rtcp_init(NULL, NULL, 0, 0, 0);
    pjmedia_rtcp_get_ntp_time(NULL, NULL);
    pjmedia_rtcp_fini(NULL);
    pjmedia_rtcp_rx_rtp(NULL, 0, 0, 0);
    pjmedia_rtcp_tx_rtp(NULL, 0);
    pjmedia_rtcp_rx_rtcp(NULL, NULL, 0);
    pjmedia_rtcp_build_rtcp(NULL, NULL, NULL);
#endif

#ifdef HAS_PJMEDIA_JBUF
    pjmedia_jbuf_create(NULL, NULL, 0, 0, 0, NULL);
    pjmedia_jbuf_set_fixed(NULL, 0);
    pjmedia_jbuf_set_adaptive(NULL, 0, 0, 0);
    pjmedia_jbuf_destroy(NULL);
    pjmedia_jbuf_put_frame(NULL, NULL, 0, 0);
    pjmedia_jbuf_get_frame(NULL, NULL, NULL);
#endif

#ifdef HAS_PJMEDIA_STREAM
    pjmedia_stream_create(NULL, NULL, NULL, NULL, NULL, NULL);
    pjmedia_stream_destroy(NULL);
    pjmedia_stream_get_port(NULL, NULL);
    pjmedia_stream_get_transport(NULL);
    pjmedia_stream_start(NULL);
    pjmedia_stream_get_stat(NULL, NULL);
    pjmedia_stream_pause(NULL, PJMEDIA_DIR_ENCODING);
    pjmedia_stream_resume(NULL, PJMEDIA_DIR_ENCODING);
    pjmedia_stream_dial_dtmf(NULL, NULL);
    pjmedia_stream_check_dtmf(NULL);
    pjmedia_stream_get_dtmf(NULL, NULL, NULL);
#endif

#ifdef HAS_PJMEDIA_TONEGEN
    pjmedia_tonegen_create(NULL, 0, 0, 0, 0, 0, NULL);
    pjmedia_tonegen_is_busy(NULL);
    pjmedia_tonegen_stop(NULL);
    pjmedia_tonegen_play(NULL, 0, NULL, 0);
    pjmedia_tonegen_play_digits(NULL, 0, NULL, 0);
    pjmedia_tonegen_get_digit_map(NULL, NULL);
    pjmedia_tonegen_set_digit_map(NULL, NULL);
#endif

#ifdef HAS_PJMEDIA_UDP_TRANSPORT
    pjmedia_transport_udp_create(NULL, NULL, 0, 0, NULL);
    pjmedia_transport_udp_close(NULL);
#endif

#ifdef HAS_PJMEDIA_FILE_PLAYER
    pjmedia_wav_player_port_create(NULL, NULL, 0, 0, 0, NULL);
    pjmedia_wav_player_port_set_pos(NULL, 0);
    pjmedia_wav_player_port_get_pos(NULL);
    pjmedia_wav_player_set_eof_cb(NULL, NULL, NULL);
#endif

#ifdef HAS_PJMEDIA_FILE_CAPTURE
    pjmedia_wav_writer_port_create(NULL, NULL, 8000, 1, 80, 16, 0, 0, NULL);
    pjmedia_wav_writer_port_get_pos(NULL);
    pjmedia_wav_writer_port_set_cb(NULL, 0, NULL, NULL);
#endif

#ifdef HAS_PJMEDIA_MEM_PLAYER
    pjmedia_mem_player_create(NULL, NULL, 1000, 8000, 1, 80, 16, 0, NULL);
#endif

#ifdef HAS_PJMEDIA_MEM_CAPTURE
    pjmedia_mem_capture_create(NULL, NULL, 1000, 8000, 1, 80, 16, 0, NULL);
#endif

#ifdef HAS_PJMEDIA_ICE
    pjmedia_ice_create(NULL, NULL, 0, NULL, NULL);
    pjmedia_ice_destroy(NULL);
    pjmedia_ice_start_init(NULL, 0, NULL, NULL, NULL);
    pjmedia_ice_init_ice(NULL, PJ_ICE_SESS_ROLE_CONTROLLED, NULL, NULL);
    pjmedia_ice_modify_sdp(NULL, NULL, NULL);
    pjmedia_ice_start_ice(NULL, NULL, NULL, 0);
    pjmedia_ice_stop_ice(NULL);
#endif

#ifdef HAS_PJMEDIA_G711_CODEC
    pjmedia_codec_g711_init(NULL);
    pjmedia_codec_g711_deinit();
#endif

#ifdef HAS_PJMEDIA_GSM_CODEC
    pjmedia_codec_gsm_init(NULL);
    pjmedia_codec_gsm_deinit();
#endif

#ifdef HAS_PJMEDIA_SPEEX_CODEC
    pjmedia_codec_speex_init(NULL, 0, 0, 0);
    pjmedia_codec_speex_deinit();
#endif

#ifdef HAS_PJMEDIA_ILBC_CODEC
    pjmedia_codec_ilbc_init(NULL, 0);
    pjmedia_codec_ilbc_deinit();
#endif

    return 0;
}