📄 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 + -