📄 sip_util.c
字号:
via = (pjsip_via_hdr*) pjsip_msg_find_hdr( tdata->msg,
PJSIP_H_VIA, NULL);
if (!via) {
/* Shouldn't happen if request was created with PJSIP API!
* But we handle the case anyway for robustness.
*/
pj_assert(!"Via header not found!");
via = pjsip_via_hdr_create(tdata->pool);
pjsip_msg_insert_first_hdr(tdata->msg, (pjsip_hdr*)via);
}
if (via->branch_param.slen == 0) {
pj_str_t tmp;
via->branch_param.ptr = pj_pool_alloc(tdata->pool,
PJSIP_MAX_BRANCH_LEN);
via->branch_param.slen = PJSIP_MAX_BRANCH_LEN;
pj_memcpy(via->branch_param.ptr, PJSIP_RFC3261_BRANCH_ID,
PJSIP_RFC3261_BRANCH_LEN);
tmp.ptr = via->branch_param.ptr + PJSIP_RFC3261_BRANCH_LEN + 2;
*(tmp.ptr-2) = 80; *(tmp.ptr-1) = 106;
pj_generate_unique_string(&tmp);
}
via->transport = pj_str(stateless_data->cur_transport->type_name);
via->sent_by = stateless_data->cur_transport->local_name;
via->rport_param = 0;
/* Send message using this transport. */
status = pjsip_transport_send( stateless_data->cur_transport,
tdata,
cur_addr,
cur_addr_len,
stateless_data,
&stateless_send_transport_cb);
if (status == PJ_SUCCESS) {
/* Recursively call this function. */
sent = tdata->buf.cur - tdata->buf.start;
stateless_send_transport_cb( stateless_data, tdata, sent );
return;
} else if (status == PJ_EPENDING) {
/* This callback will be called later. */
return;
} else {
/* Recursively call this function. */
sent = -status;
stateless_send_transport_cb( stateless_data, tdata, sent );
return;
}
}
}
/* Resolver callback for sending stateless request. */
static void
stateless_send_resolver_callback( pj_status_t status,
void *token,
const struct pjsip_server_addresses *addr)
{
pjsip_send_state *stateless_data = token;
/* Fail on server resolution. */
if (status != PJ_SUCCESS) {
if (stateless_data->app_cb) {
pj_bool_t cont = PJ_FALSE;
(*stateless_data->app_cb)(stateless_data, -status, &cont);
}
pjsip_tx_data_dec_ref(stateless_data->tdata);
return;
}
/* Copy server addresses */
pj_memcpy( &stateless_data->addr, addr, sizeof(pjsip_server_addresses));
/* Process the addresses. */
stateless_send_transport_cb( stateless_data, stateless_data->tdata,
-PJ_EPENDING);
}
/*
* Send stateless request.
* The sending process consists of several stages:
* - determine which host to contact (#pjsip_get_request_addr).
* - resolve the host (#pjsip_endpt_resolve)
* - establish transport (#pjsip_endpt_acquire_transport)
* - send the message (#pjsip_transport_send)
*/
PJ_DEF(pj_status_t)
pjsip_endpt_send_request_stateless(pjsip_endpoint *endpt,
pjsip_tx_data *tdata,
void *token,
void (*cb)(pjsip_send_state*,
pj_ssize_t sent,
pj_bool_t *cont))
{
pjsip_host_info dest_info;
pjsip_send_state *stateless_data;
pj_status_t status;
PJ_ASSERT_RETURN(endpt && tdata, PJ_EINVAL);
/* Get destination name to contact. */
status = pjsip_process_route_set(tdata, &dest_info);
if (status != PJ_SUCCESS)
return status;
/* Keep stateless data. */
stateless_data = pj_pool_zalloc(tdata->pool, sizeof(pjsip_send_state));
stateless_data->token = token;
stateless_data->endpt = endpt;
stateless_data->tdata = tdata;
stateless_data->app_cb = cb;
/* Resolve destination host.
* The processing then resumed when the resolving callback is called.
*/
pjsip_endpt_resolve( endpt, tdata->pool, &dest_info, stateless_data,
&stateless_send_resolver_callback);
return PJ_SUCCESS;
}
/*
* Determine which address (and transport) to use to send response message
* based on the received request. This function follows the specification
* in section 18.2.2 of RFC 3261 and RFC 3581 for calculating the destination
* address and transport.
*/
PJ_DEF(pj_status_t) pjsip_get_response_addr( pj_pool_t *pool,
pjsip_rx_data *rdata,
pjsip_response_addr *res_addr )
{
pjsip_transport *src_transport = rdata->tp_info.transport;
/* Check arguments. */
PJ_ASSERT_RETURN(pool && rdata && res_addr, PJ_EINVAL);
/* rdata must be a request message! */
PJ_ASSERT_RETURN(rdata->msg_info.msg->type == PJSIP_REQUEST_MSG,
PJ_EINVAL);
/* All requests must have "received" parameter.
* This must always be done in transport layer.
*/
pj_assert(rdata->msg_info.via->recvd_param.slen != 0);
/* Do the calculation based on RFC 3261 Section 18.2.2 and RFC 3581 */
if (PJSIP_TRANSPORT_IS_RELIABLE(src_transport)) {
/* For reliable protocol such as TCP or SCTP, or TLS over those, the
* response MUST be sent using the existing connection to the source
* of the original request that created the transaction, if that
* connection is still open.
* If that connection is no longer open, the server SHOULD open a
* connection to the IP address in the received parameter, if present,
* using the port in the sent-by value, or the default port for that
* transport, if no port is specified.
* If that connection attempt fails, the server SHOULD use the
* procedures in [4] for servers in order to determine the IP address
* and port to open the connection and send the response to.
*/
res_addr->transport = rdata->tp_info.transport;
pj_memcpy(&res_addr->addr, &rdata->pkt_info.src_addr,
rdata->pkt_info.src_addr_len);
res_addr->addr_len = rdata->pkt_info.src_addr_len;
res_addr->dst_host.type = src_transport->key.type;
res_addr->dst_host.flag = src_transport->flag;
pj_strdup( pool, &res_addr->dst_host.addr.host,
&rdata->msg_info.via->recvd_param);
res_addr->dst_host.addr.port = rdata->msg_info.via->sent_by.port;
if (res_addr->dst_host.addr.port == 0) {
res_addr->dst_host.addr.port =
pjsip_transport_get_default_port_for_type(res_addr->dst_host.type);
}
} else if (rdata->msg_info.via->maddr_param.slen) {
/* Otherwise, if the Via header field value contains a maddr parameter,
* the response MUST be forwarded to the address listed there, using
* the port indicated in sent-by, or port 5060 if none is present.
* If the address is a multicast address, the response SHOULD be sent
* using the TTL indicated in the ttl parameter, or with a TTL of 1 if
* that parameter is not present.
*/
res_addr->transport = NULL;
res_addr->dst_host.type = src_transport->key.type;
res_addr->dst_host.flag = src_transport->flag;
pj_strdup( pool, &res_addr->dst_host.addr.host,
&rdata->msg_info.via->maddr_param);
res_addr->dst_host.addr.port = rdata->msg_info.via->sent_by.port;
if (res_addr->dst_host.addr.port == 0)
res_addr->dst_host.addr.port = 5060;
} else if (rdata->msg_info.via->rport_param >= 0) {
/* There is both a "received" parameter and an "rport" parameter,
* the response MUST be sent to the IP address listed in the "received"
* parameter, and the port in the "rport" parameter.
* The response MUST be sent from the same address and port that the
* corresponding request was received on.
*/
res_addr->transport = rdata->tp_info.transport;
pj_memcpy(&res_addr->addr, &rdata->pkt_info.src_addr,
rdata->pkt_info.src_addr_len);
res_addr->addr_len = rdata->pkt_info.src_addr_len;
res_addr->dst_host.type = src_transport->key.type;
res_addr->dst_host.flag = src_transport->flag;
pj_strdup( pool, &res_addr->dst_host.addr.host,
&rdata->msg_info.via->recvd_param);
res_addr->dst_host.addr.port = rdata->msg_info.via->sent_by.port;
if (res_addr->dst_host.addr.port == 0) {
res_addr->dst_host.addr.port =
pjsip_transport_get_default_port_for_type(res_addr->dst_host.type);
}
} else {
res_addr->transport = NULL;
res_addr->dst_host.type = src_transport->key.type;
res_addr->dst_host.flag = src_transport->flag;
pj_strdup( pool, &res_addr->dst_host.addr.host,
&rdata->msg_info.via->recvd_param);
res_addr->dst_host.addr.port = rdata->msg_info.via->sent_by.port;
if (res_addr->dst_host.addr.port == 0) {
res_addr->dst_host.addr.port =
pjsip_transport_get_default_port_for_type(res_addr->dst_host.type);
}
}
return PJ_SUCCESS;
}
/*
* Callback called by transport during send_response.
*/
static void send_response_transport_cb(void *token, pjsip_tx_data *tdata,
pj_ssize_t sent)
{
pjsip_send_state *send_state = token;
pj_bool_t cont = PJ_FALSE;
/* Call callback, if any. */
if (send_state->app_cb)
(*send_state->app_cb)(send_state, sent, &cont);
/* Decrement transport reference counter. */
pjsip_transport_dec_ref(send_state->cur_transport);
/* Decrement transmit data ref counter. */
pjsip_tx_data_dec_ref(tdata);
}
/*
* Resolver calback during send_response.
*/
static void send_response_resolver_cb( pj_status_t status, void *token,
const pjsip_server_addresses *addr )
{
pjsip_send_state *send_state = token;
if (status != PJ_SUCCESS) {
if (send_state->app_cb) {
pj_bool_t cont = PJ_FALSE;
(*send_state->app_cb)(send_state, -status, &cont);
}
pjsip_tx_data_dec_ref(send_state->tdata);
return;
}
/* Only handle the first address resolved. */
/* Acquire transport. */
status = pjsip_endpt_acquire_transport( send_state->endpt,
addr->entry[0].type,
&addr->entry[0].addr,
addr->entry[0].addr_len,
&send_state->tdata->tp_sel,
&send_state->cur_transport);
if (status != PJ_SUCCESS) {
if (send_state->app_cb) {
pj_bool_t cont = PJ_FALSE;
(*send_state->app_cb)(send_state, -status, &cont);
}
pjsip_tx_data_dec_ref(send_state->tdata);
return;
}
/* Update address in send_state. */
send_state->addr = *addr;
/* Send response using the transoprt. */
status = pjsip_transport_send( send_state->cur_transport,
send_state->tdata,
&addr->entry[0].addr,
addr->entry[0].addr_len,
send_state,
&send_response_transport_cb);
if (status == PJ_SUCCESS) {
pj_ssize_t sent = send_state->tdata->buf.cur -
send_state->tdata->buf.start;
send_response_transport_cb(send_state, send_state->tdata, sent);
} else if (status == PJ_EPENDING) {
/* Transport callback will be called later. */
} else {
send_response_transport_cb(send_state, send_state->tdata, -status);
}
}
/*
* Send response.
*/
PJ_DEF(pj_status_t) pjsip_endpt_send_response( pjsip_endpoint *endpt,
pjsip_response_addr *res_addr,
pjsip_tx_data *tdata,
void *token,
void (*cb)(pjsip_send_state*,
pj_ssize_t sent,
pj_bool_t *cont))
{
/* Determine which transports and addresses to send the response,
* based on Section 18.2.2 of RFC 3261.
*/
pjsip_send_state *send_state;
pj_status_t status;
/* Create structure to keep the sending state. */
send_state = pj_pool_zalloc(tdata->pool, sizeof(pjsip_send_state));
send_state->endpt = endpt;
send_state->tdata = tdata;
send_state->token = token;
send_state->app_cb = cb;
if (res_addr->transport != NULL) {
send_state->cur_transport = res_addr->transport;
pjsip_transport_add_ref(send_state->cur_transport);
status = pjsip_transport_send( send_state->cur_transport, tdata,
&res_addr->addr,
res_addr->addr_len,
send_state,
&send_response_transport_cb );
if (status == PJ_SUCCESS) {
pj_ssize_t sent = tdata->buf.cur - tdata->buf.start;
send_response_transport_cb(send_state, tdata, sent);
return PJ_SUCCESS;
} else if (status == PJ_EPENDING) {
/* Callback will be called later. */
return PJ_SUCCESS;
} else {
pjsip_transport_dec_ref(send_state->cur_transport);
return status;
}
} else {
pjsip_endpt_resolve(endpt, tdata->pool, &res_addr->dst_host,
send_state, &send_response_resolver_cb);
return PJ_SUCCESS;
}
}
/*
* Send response combo
*/
PJ_DEF(pj_status_t) pjsip_endpt_send_response2( pjsip_endpoint *endpt,
pjsip_rx_data *rdata,
pjsip_tx_data *tdata,
void *token,
void (*cb)(pjsip_send_state*,
pj_ssize_t sent,
pj_bool_t *cont))
{
pjsip_response_addr res_addr;
pj_status_t status;
status = pjsip_get_response_addr(tdata->pool, rdata, &res_addr);
if (status != PJ_SUCCESS) {
pjsip_tx_data_dec_ref(tdata);
return PJ_SUCCESS;
}
status = pjsip_endpt_send_response(endpt, &res_addr, tdata, token, cb);
return status;
}
/*
* Send response
*/
PJ_DEF(pj_status_t) pjsip_endpt_respond_stateless( pjsip_endpoint *endpt,
pjsip_rx_data *rdata,
int st_code,
const pj_str_t *st_text,
const pjsip_hdr *hdr_list,
const pjsip_msg_body *body)
{
pj_status_t status;
pjsip_response_addr res_addr;
pjsip_tx_data *tdata;
/* Verify arguments. */
PJ_ASSERT_RETURN(endpt && rdata, PJ_EINVAL);
PJ_ASSERT_RETURN(rdata->msg_info.msg->type == PJSIP_REQUEST_MSG,
PJSIP_ENOTREQUESTMSG);
/* Check that no UAS transaction has been created for this request.
* If UAS transaction has been created for this request, application
* MUST send the response statefully using that transaction.
*/
PJ_ASSERT_RETURN(pjsip_rdata_get_tsx(rdata)==NULL, PJ_EINVALIDOP);
/* Create response message */
status = pjsip_endpt_create_response( endpt, rdata, st_code, st_text,
&tdata);
if (status != PJ_SUCCESS)
return status;
/* Add the message headers, if any */
if (hdr_list) {
const pjsip_hdr *hdr = hdr_list->next;
while (hdr != hdr_list) {
pjsip_msg_add_hdr( tdata->msg, pjsip_hdr_clone(tdata->pool, hdr) );
hdr = hdr->next;
}
}
/* Add the message body, if any. */
if (body) {
tdata->msg->body = pjsip_msg_body_clone( tdata->pool, body );
if (tdata->msg->body == NULL) {
pjsip_tx_data_dec_ref(tdata);
return status;
}
}
/* Get where to send request. */
status = pjsip_get_response_addr( tdata->pool, rdata, &res_addr );
if (status != PJ_SUCCESS) {
pjsip_tx_data_dec_ref(tdata);
return status;
}
/* Send! */
status = pjsip_endpt_send_response( endpt, &res_addr, tdata, NULL, NULL );
return status;
}
/*
* Get the event string from the event ID.
*/
PJ_DEF(const char *) pjsip_event_str(pjsip_event_id_e e)
{
return event_str[e];
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -